Implement tail call on MIPS.
[sljit.git] / sljit_src / sljitNativeMIPS_common.c
blobbbd3183aa18a50fefb153dc0785e302a829202d2
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, 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, 12, 18, 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_UEQ_S (HI(17) | CMP_FMT_S | LO(3))
155 #define C_ULE_S (HI(17) | CMP_FMT_S | LO(7))
156 #define C_ULT_S (HI(17) | CMP_FMT_S | LO(5))
157 #define C_UN_S (HI(17) | CMP_FMT_S | LO(1))
158 #define C_FD (FD(TMP_FREG3))
159 #else /* SLJIT_MIPS_REV < 6 */
160 #define C_UEQ_S (HI(17) | FMT_S | LO(51))
161 #define C_ULE_S (HI(17) | FMT_S | LO(55))
162 #define C_ULT_S (HI(17) | FMT_S | LO(53))
163 #define C_UN_S (HI(17) | FMT_S | LO(49))
164 #define C_FD (0)
165 #endif /* SLJIT_MIPS_REV >= 6 */
166 #define CVT_S_S (HI(17) | FMT_S | LO(32))
167 #define DADDIU (HI(25))
168 #define DADDU (HI(0) | LO(45))
169 #if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 6)
170 #define DDIV (HI(0) | (2 << 6) | LO(30))
171 #define DDIVU (HI(0) | (2 << 6) | LO(31))
172 #define DMOD (HI(0) | (3 << 6) | LO(30))
173 #define DMODU (HI(0) | (3 << 6) | LO(31))
174 #define DIV (HI(0) | (2 << 6) | LO(26))
175 #define DIVU (HI(0) | (2 << 6) | LO(27))
176 #define DMUH (HI(0) | (3 << 6) | LO(28))
177 #define DMUHU (HI(0) | (3 << 6) | LO(29))
178 #define DMUL (HI(0) | (2 << 6) | LO(28))
179 #define DMULU (HI(0) | (2 << 6) | LO(29))
180 #else /* SLJIT_MIPS_REV < 6 */
181 #define DDIV (HI(0) | LO(30))
182 #define DDIVU (HI(0) | LO(31))
183 #define DIV (HI(0) | LO(26))
184 #define DIVU (HI(0) | LO(27))
185 #define DMULT (HI(0) | LO(28))
186 #define DMULTU (HI(0) | LO(29))
187 #endif /* SLJIT_MIPS_REV >= 6 */
188 #define DIV_S (HI(17) | FMT_S | LO(3))
189 #define DINSU (HI(31) | LO(6))
190 #define DSLL (HI(0) | LO(56))
191 #define DSLL32 (HI(0) | LO(60))
192 #define DSLLV (HI(0) | LO(20))
193 #define DSRA (HI(0) | LO(59))
194 #define DSRA32 (HI(0) | LO(63))
195 #define DSRAV (HI(0) | LO(23))
196 #define DSRL (HI(0) | LO(58))
197 #define DSRL32 (HI(0) | LO(62))
198 #define DSRLV (HI(0) | LO(22))
199 #define DSUBU (HI(0) | LO(47))
200 #define J (HI(2))
201 #define JAL (HI(3))
202 #define JALR (HI(0) | LO(9))
203 #if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 6)
204 #define JR (HI(0) | LO(9))
205 #else /* SLJIT_MIPS_REV < 6 */
206 #define JR (HI(0) | LO(8))
207 #endif /* SLJIT_MIPS_REV >= 6 */
208 #define LD (HI(55))
209 #define LDC1 (HI(53))
210 #define LUI (HI(15))
211 #define LW (HI(35))
212 #define LWC1 (HI(49))
213 #define MFC1 (HI(17))
214 #if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 6)
215 #define MOD (HI(0) | (3 << 6) | LO(26))
216 #define MODU (HI(0) | (3 << 6) | LO(27))
217 #else /* SLJIT_MIPS_REV < 6 */
218 #define MFHI (HI(0) | LO(16))
219 #define MFLO (HI(0) | LO(18))
220 #endif /* SLJIT_MIPS_REV >= 6 */
221 #define MOV_S (HI(17) | FMT_S | LO(6))
222 #define MTC1 (HI(17) | (4 << 21))
223 #if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 6)
224 #define MUH (HI(0) | (3 << 6) | LO(24))
225 #define MUHU (HI(0) | (3 << 6) | LO(25))
226 #define MUL (HI(0) | (2 << 6) | LO(24))
227 #define MULU (HI(0) | (2 << 6) | LO(25))
228 #else /* SLJIT_MIPS_REV < 6 */
229 #define MULT (HI(0) | LO(24))
230 #define MULTU (HI(0) | LO(25))
231 #endif /* SLJIT_MIPS_REV >= 6 */
232 #define MUL_S (HI(17) | FMT_S | LO(2))
233 #define NEG_S (HI(17) | FMT_S | LO(7))
234 #define NOP (HI(0) | LO(0))
235 #define NOR (HI(0) | LO(39))
236 #define OR (HI(0) | LO(37))
237 #define ORI (HI(13))
238 #define SD (HI(63))
239 #define SDC1 (HI(61))
240 #define SLT (HI(0) | LO(42))
241 #define SLTI (HI(10))
242 #define SLTIU (HI(11))
243 #define SLTU (HI(0) | LO(43))
244 #define SLL (HI(0) | LO(0))
245 #define SLLV (HI(0) | LO(4))
246 #define SRL (HI(0) | LO(2))
247 #define SRLV (HI(0) | LO(6))
248 #define SRA (HI(0) | LO(3))
249 #define SRAV (HI(0) | LO(7))
250 #define SUB_S (HI(17) | FMT_S | LO(1))
251 #define SUBU (HI(0) | LO(35))
252 #define SW (HI(43))
253 #define SWC1 (HI(57))
254 #define TRUNC_W_S (HI(17) | FMT_S | LO(13))
255 #define XOR (HI(0) | LO(38))
256 #define XORI (HI(14))
258 #if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 1)
259 #define CLZ (HI(28) | LO(32))
260 #if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 6)
261 #define DCLZ (LO(18))
262 #else /* SLJIT_MIPS_REV < 6 */
263 #define DCLZ (HI(28) | LO(36))
264 #define MOVF (HI(0) | (0 << 16) | LO(1))
265 #define MOVN (HI(0) | LO(11))
266 #define MOVT (HI(0) | (1 << 16) | LO(1))
267 #define MOVZ (HI(0) | LO(10))
268 #define MUL (HI(28) | LO(2))
269 #endif /* SLJIT_MIPS_REV >= 6 */
270 #define PREF (HI(51))
271 #define PREFX (HI(19) | LO(15))
272 #define SEB (HI(31) | (16 << 6) | LO(32))
273 #define SEH (HI(31) | (24 << 6) | LO(32))
274 #endif /* SLJIT_MIPS_REV >= 1 */
276 #if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)
277 #define ADDU_W ADDU
278 #define ADDIU_W ADDIU
279 #define SLL_W SLL
280 #define SUBU_W SUBU
281 #else
282 #define ADDU_W DADDU
283 #define ADDIU_W DADDIU
284 #define SLL_W DSLL
285 #define SUBU_W DSUBU
286 #endif
288 #define SIMM_MAX (0x7fff)
289 #define SIMM_MIN (-0x8000)
290 #define UIMM_MAX (0xffff)
292 /* dest_reg is the absolute name of the register
293 Useful for reordering instructions in the delay slot. */
294 static sljit_s32 push_inst(struct sljit_compiler *compiler, sljit_ins ins, sljit_s32 delay_slot)
296 sljit_ins *ptr = (sljit_ins*)ensure_buf(compiler, sizeof(sljit_ins));
297 SLJIT_ASSERT(delay_slot == MOVABLE_INS || delay_slot >= UNMOVABLE_INS
298 || (sljit_ins)delay_slot == ((ins >> 11) & 0x1f)
299 || (sljit_ins)delay_slot == ((ins >> 16) & 0x1f));
300 FAIL_IF(!ptr);
301 *ptr = ins;
302 compiler->size++;
303 compiler->delay_slot = delay_slot;
304 return SLJIT_SUCCESS;
307 static SLJIT_INLINE sljit_ins invert_branch(sljit_uw flags)
309 if (flags & IS_BIT26_COND)
310 return (1 << 26);
311 #if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 6)
312 if (flags & IS_BIT23_COND)
313 return (1 << 23);
314 #endif /* SLJIT_MIPS_REV >= 6 */
315 return (1 << 16);
318 static SLJIT_INLINE sljit_ins* detect_jump_type(struct sljit_jump *jump, sljit_ins *code_ptr, sljit_ins *code, sljit_sw executable_offset)
320 sljit_sw diff;
321 sljit_uw target_addr;
322 sljit_ins *inst;
323 sljit_ins saved_inst;
325 #if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)
326 if (jump->flags & (SLJIT_REWRITABLE_JUMP | IS_CALL))
327 return code_ptr;
328 #else
329 if (jump->flags & SLJIT_REWRITABLE_JUMP)
330 return code_ptr;
331 #endif
333 if (jump->flags & JUMP_ADDR)
334 target_addr = jump->u.target;
335 else {
336 SLJIT_ASSERT(jump->flags & JUMP_LABEL);
337 target_addr = (sljit_uw)(code + jump->u.label->size) + (sljit_uw)executable_offset;
340 inst = (sljit_ins *)jump->addr;
341 if (jump->flags & IS_COND)
342 inst--;
344 #if (defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64)
345 if (jump->flags & IS_CALL)
346 goto keep_address;
347 #endif
349 /* B instructions. */
350 if (jump->flags & IS_MOVABLE) {
351 diff = ((sljit_sw)target_addr - (sljit_sw)inst - executable_offset) >> 2;
352 if (diff <= SIMM_MAX && diff >= SIMM_MIN) {
353 jump->flags |= PATCH_B;
355 if (!(jump->flags & IS_COND)) {
356 inst[0] = inst[-1];
357 inst[-1] = (jump->flags & IS_JAL) ? BAL : B;
358 jump->addr -= sizeof(sljit_ins);
359 return inst;
361 saved_inst = inst[0];
362 inst[0] = inst[-1];
363 inst[-1] = saved_inst ^ invert_branch(jump->flags);
364 jump->addr -= 2 * sizeof(sljit_ins);
365 return inst;
368 else {
369 diff = ((sljit_sw)target_addr - (sljit_sw)(inst + 1) - executable_offset) >> 2;
370 if (diff <= SIMM_MAX && diff >= SIMM_MIN) {
371 jump->flags |= PATCH_B;
373 if (!(jump->flags & IS_COND)) {
374 inst[0] = (jump->flags & IS_JAL) ? BAL : B;
375 inst[1] = NOP;
376 return inst + 1;
378 inst[0] ^= invert_branch(jump->flags);
379 inst[1] = NOP;
380 jump->addr -= sizeof(sljit_ins);
381 return inst + 1;
385 if (jump->flags & IS_COND) {
386 if ((jump->flags & IS_MOVABLE) && (target_addr & ~(sljit_uw)0xfffffff) == ((jump->addr + 2 * sizeof(sljit_ins)) & ~(sljit_uw)0xfffffff)) {
387 jump->flags |= PATCH_J;
388 saved_inst = inst[0];
389 inst[0] = inst[-1];
390 inst[-1] = (saved_inst & 0xffff0000) | 3;
391 inst[1] = J;
392 inst[2] = NOP;
393 return inst + 2;
395 else if ((target_addr & ~(sljit_uw)0xfffffff) == ((jump->addr + 3 * sizeof(sljit_ins)) & ~(sljit_uw)0xfffffff)) {
396 jump->flags |= PATCH_J;
397 inst[0] = (inst[0] & 0xffff0000) | 3;
398 inst[1] = NOP;
399 inst[2] = J;
400 inst[3] = NOP;
401 jump->addr += sizeof(sljit_ins);
402 return inst + 3;
405 else {
406 /* J instuctions. */
407 if ((jump->flags & IS_MOVABLE) && (target_addr & ~(sljit_uw)0xfffffff) == (jump->addr & ~(sljit_uw)0xfffffff)) {
408 jump->flags |= PATCH_J;
409 inst[0] = inst[-1];
410 inst[-1] = (jump->flags & IS_JAL) ? JAL : J;
411 jump->addr -= sizeof(sljit_ins);
412 return inst;
415 if ((target_addr & ~(sljit_uw)0xfffffff) == ((jump->addr + sizeof(sljit_ins)) & ~(sljit_uw)0xfffffff)) {
416 jump->flags |= PATCH_J;
417 inst[0] = (jump->flags & IS_JAL) ? JAL : J;
418 inst[1] = NOP;
419 return inst + 1;
423 #if (defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64)
424 keep_address:
425 if (target_addr <= 0x7fffffff) {
426 jump->flags |= PATCH_ABS32;
427 if (jump->flags & IS_COND) {
428 inst[0] -= 4;
429 inst++;
431 inst[2] = inst[6];
432 inst[3] = inst[7];
433 return inst + 3;
435 if (target_addr <= 0x7fffffffffffl) {
436 jump->flags |= PATCH_ABS48;
437 if (jump->flags & IS_COND) {
438 inst[0] -= 2;
439 inst++;
441 inst[4] = inst[6];
442 inst[5] = inst[7];
443 return inst + 5;
445 #endif
447 return code_ptr;
450 #ifdef __GNUC__
451 static __attribute__ ((noinline)) void sljit_cache_flush(void* code, void* code_ptr)
453 SLJIT_CACHE_FLUSH(code, code_ptr);
455 #endif
457 #if (defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64)
459 static SLJIT_INLINE sljit_sw put_label_get_length(struct sljit_put_label *put_label, sljit_uw max_label)
461 if (max_label < 0x80000000l) {
462 put_label->flags = 0;
463 return 1;
466 if (max_label < 0x800000000000l) {
467 put_label->flags = 1;
468 return 3;
471 put_label->flags = 2;
472 return 5;
475 static SLJIT_INLINE void put_label_set(struct sljit_put_label *put_label)
477 sljit_uw addr = put_label->label->addr;
478 sljit_ins *inst = (sljit_ins *)put_label->addr;
479 sljit_u32 reg = *inst;
481 if (put_label->flags == 0) {
482 SLJIT_ASSERT(addr < 0x80000000l);
483 inst[0] = LUI | T(reg) | IMM(addr >> 16);
485 else if (put_label->flags == 1) {
486 SLJIT_ASSERT(addr < 0x800000000000l);
487 inst[0] = LUI | T(reg) | IMM(addr >> 32);
488 inst[1] = ORI | S(reg) | T(reg) | IMM((addr >> 16) & 0xffff);
489 inst[2] = DSLL | T(reg) | D(reg) | SH_IMM(16);
490 inst += 2;
492 else {
493 inst[0] = LUI | T(reg) | IMM(addr >> 48);
494 inst[1] = ORI | S(reg) | T(reg) | IMM((addr >> 32) & 0xffff);
495 inst[2] = DSLL | T(reg) | D(reg) | SH_IMM(16);
496 inst[3] = ORI | S(reg) | T(reg) | IMM((addr >> 16) & 0xffff);
497 inst[4] = DSLL | T(reg) | D(reg) | SH_IMM(16);
498 inst += 4;
501 inst[1] = ORI | S(reg) | T(reg) | IMM(addr & 0xffff);
504 #endif
506 SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compiler)
508 struct sljit_memory_fragment *buf;
509 sljit_ins *code;
510 sljit_ins *code_ptr;
511 sljit_ins *buf_ptr;
512 sljit_ins *buf_end;
513 sljit_uw word_count;
514 sljit_uw next_addr;
515 sljit_sw executable_offset;
516 sljit_uw addr;
518 struct sljit_label *label;
519 struct sljit_jump *jump;
520 struct sljit_const *const_;
521 struct sljit_put_label *put_label;
523 CHECK_ERROR_PTR();
524 CHECK_PTR(check_sljit_generate_code(compiler));
525 reverse_buf(compiler);
527 code = (sljit_ins*)SLJIT_MALLOC_EXEC(compiler->size * sizeof(sljit_ins), compiler->exec_allocator_data);
528 PTR_FAIL_WITH_EXEC_IF(code);
529 buf = compiler->buf;
531 code_ptr = code;
532 word_count = 0;
533 next_addr = 0;
534 executable_offset = SLJIT_EXEC_OFFSET(code);
536 label = compiler->labels;
537 jump = compiler->jumps;
538 const_ = compiler->consts;
539 put_label = compiler->put_labels;
541 do {
542 buf_ptr = (sljit_ins*)buf->memory;
543 buf_end = buf_ptr + (buf->used_size >> 2);
544 do {
545 *code_ptr = *buf_ptr++;
546 if (next_addr == word_count) {
547 SLJIT_ASSERT(!label || label->size >= word_count);
548 SLJIT_ASSERT(!jump || jump->addr >= word_count);
549 SLJIT_ASSERT(!const_ || const_->addr >= word_count);
550 SLJIT_ASSERT(!put_label || put_label->addr >= word_count);
552 /* These structures are ordered by their address. */
553 if (label && label->size == word_count) {
554 label->addr = (sljit_uw)SLJIT_ADD_EXEC_OFFSET(code_ptr, executable_offset);
555 label->size = (sljit_uw)(code_ptr - code);
556 label = label->next;
558 if (jump && jump->addr == word_count) {
559 #if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)
560 jump->addr = (sljit_uw)(code_ptr - 3);
561 #else
562 jump->addr = (sljit_uw)(code_ptr - 7);
563 #endif
564 code_ptr = detect_jump_type(jump, code_ptr, code, executable_offset);
565 jump = jump->next;
567 if (const_ && const_->addr == word_count) {
568 const_->addr = (sljit_uw)code_ptr;
569 const_ = const_->next;
571 if (put_label && put_label->addr == word_count) {
572 SLJIT_ASSERT(put_label->label);
573 put_label->addr = (sljit_uw)code_ptr;
574 #if (defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64)
575 code_ptr += put_label_get_length(put_label, (sljit_uw)(SLJIT_ADD_EXEC_OFFSET(code, executable_offset) + put_label->label->size));
576 word_count += 5;
577 #endif
578 put_label = put_label->next;
580 next_addr = compute_next_addr(label, jump, const_, put_label);
582 code_ptr ++;
583 word_count ++;
584 } while (buf_ptr < buf_end);
586 buf = buf->next;
587 } while (buf);
589 if (label && label->size == word_count) {
590 label->addr = (sljit_uw)code_ptr;
591 label->size = (sljit_uw)(code_ptr - code);
592 label = label->next;
595 SLJIT_ASSERT(!label);
596 SLJIT_ASSERT(!jump);
597 SLJIT_ASSERT(!const_);
598 SLJIT_ASSERT(!put_label);
599 SLJIT_ASSERT(code_ptr - code <= (sljit_sw)compiler->size);
601 jump = compiler->jumps;
602 while (jump) {
603 do {
604 addr = (jump->flags & JUMP_LABEL) ? jump->u.label->addr : jump->u.target;
605 buf_ptr = (sljit_ins *)jump->addr;
607 if (jump->flags & PATCH_B) {
608 addr = (sljit_uw)((sljit_sw)(addr - (sljit_uw)SLJIT_ADD_EXEC_OFFSET(buf_ptr, executable_offset) - sizeof(sljit_ins)) >> 2);
609 SLJIT_ASSERT((sljit_sw)addr <= SIMM_MAX && (sljit_sw)addr >= SIMM_MIN);
610 buf_ptr[0] = (buf_ptr[0] & 0xffff0000) | ((sljit_ins)addr & 0xffff);
611 break;
613 if (jump->flags & PATCH_J) {
614 SLJIT_ASSERT((addr & ~(sljit_uw)0xfffffff)
615 == (((sljit_uw)SLJIT_ADD_EXEC_OFFSET(buf_ptr, executable_offset) + sizeof(sljit_ins)) & ~(sljit_uw)0xfffffff));
616 buf_ptr[0] |= (sljit_ins)(addr >> 2) & 0x03ffffff;
617 break;
620 /* Set the fields of immediate loads. */
621 #if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)
622 SLJIT_ASSERT(((buf_ptr[0] | buf_ptr[1]) & 0xffff) == 0);
623 buf_ptr[0] |= (sljit_ins)(addr >> 16) & 0xffff;
624 buf_ptr[1] |= (sljit_ins)addr & 0xffff;
625 #else
626 if (jump->flags & PATCH_ABS32) {
627 SLJIT_ASSERT(addr <= 0x7fffffff);
628 SLJIT_ASSERT(((buf_ptr[0] | buf_ptr[1]) & 0xffff) == 0);
629 buf_ptr[0] |= (sljit_ins)(addr >> 16) & 0xffff;
630 buf_ptr[1] |= (sljit_ins)addr & 0xffff;
631 break;
634 if (jump->flags & PATCH_ABS48) {
635 SLJIT_ASSERT(addr <= 0x7fffffffffffl);
636 SLJIT_ASSERT(((buf_ptr[0] | buf_ptr[1] | buf_ptr[3]) & 0xffff) == 0);
637 buf_ptr[0] |= (sljit_ins)(addr >> 32) & 0xffff;
638 buf_ptr[1] |= (sljit_ins)(addr >> 16) & 0xffff;
639 buf_ptr[3] |= (sljit_ins)addr & 0xffff;
640 break;
643 SLJIT_ASSERT(((buf_ptr[0] | buf_ptr[1] | buf_ptr[3] | buf_ptr[5]) & 0xffff) == 0);
644 buf_ptr[0] |= (sljit_ins)(addr >> 48) & 0xffff;
645 buf_ptr[1] |= (sljit_ins)(addr >> 32) & 0xffff;
646 buf_ptr[3] |= (sljit_ins)(addr >> 16) & 0xffff;
647 buf_ptr[5] |= (sljit_ins)addr & 0xffff;
648 #endif
649 } while (0);
650 jump = jump->next;
653 put_label = compiler->put_labels;
654 while (put_label) {
655 #if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)
656 addr = put_label->label->addr;
657 buf_ptr = (sljit_ins *)put_label->addr;
659 SLJIT_ASSERT((buf_ptr[0] & 0xffe00000) == LUI && (buf_ptr[1] & 0xfc000000) == ORI);
660 buf_ptr[0] |= (addr >> 16) & 0xffff;
661 buf_ptr[1] |= addr & 0xffff;
662 #else
663 put_label_set(put_label);
664 #endif
665 put_label = put_label->next;
668 compiler->error = SLJIT_ERR_COMPILED;
669 compiler->executable_offset = executable_offset;
670 compiler->executable_size = (sljit_uw)(code_ptr - code) * sizeof(sljit_ins);
672 code = (sljit_ins *)SLJIT_ADD_EXEC_OFFSET(code, executable_offset);
673 code_ptr = (sljit_ins *)SLJIT_ADD_EXEC_OFFSET(code_ptr, executable_offset);
675 #ifndef __GNUC__
676 SLJIT_CACHE_FLUSH(code, code_ptr);
677 #else
678 /* GCC workaround for invalid code generation with -O2. */
679 sljit_cache_flush(code, code_ptr);
680 #endif
681 SLJIT_UPDATE_WX_FLAGS(code, code_ptr, 1);
682 return code;
685 SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_has_cpu_feature(sljit_s32 feature_type)
687 #if defined(__GNUC__) && !defined(SLJIT_IS_FPU_AVAILABLE)
688 sljit_sw fir = 0;
689 #endif /* __GNUC__ && !SLJIT_IS_FPU_AVAILABLE */
691 switch (feature_type) {
692 case SLJIT_HAS_FPU:
693 #ifdef SLJIT_IS_FPU_AVAILABLE
694 return SLJIT_IS_FPU_AVAILABLE;
695 #elif defined(__GNUC__)
696 __asm__ ("cfc1 %0, $0" : "=r"(fir));
697 return (fir >> 22) & 0x1;
698 #else
699 #error "FIR check is not implemented for this architecture"
700 #endif
701 case SLJIT_HAS_ZERO_REGISTER:
702 return 1;
704 #if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 1)
705 case SLJIT_HAS_CLZ:
706 case SLJIT_HAS_CMOV:
707 case SLJIT_HAS_PREFETCH:
708 return 1;
709 #endif /* SLJIT_MIPS_REV >= 1 */
711 default:
712 return 0;
716 /* --------------------------------------------------------------------- */
717 /* Entry, exit */
718 /* --------------------------------------------------------------------- */
720 /* Creates an index in data_transfer_insts array. */
721 #define LOAD_DATA 0x01
722 #define WORD_DATA 0x00
723 #define BYTE_DATA 0x02
724 #define HALF_DATA 0x04
725 #define INT_DATA 0x06
726 #define SIGNED_DATA 0x08
727 /* Separates integer and floating point registers */
728 #define GPR_REG 0x0f
729 #define DOUBLE_DATA 0x10
730 #define SINGLE_DATA 0x12
732 #define MEM_MASK 0x1f
734 #define ARG_TEST 0x00020
735 #define ALT_KEEP_CACHE 0x00040
736 #define CUMULATIVE_OP 0x00080
737 #define LOGICAL_OP 0x00100
738 #define IMM_OP 0x00200
739 #define MOVE_OP 0x00400
740 #define SRC2_IMM 0x00800
742 #define UNUSED_DEST 0x01000
743 #define REG_DEST 0x02000
744 #define REG1_SOURCE 0x04000
745 #define REG2_SOURCE 0x08000
746 #define SLOW_SRC1 0x10000
747 #define SLOW_SRC2 0x20000
748 #define SLOW_DEST 0x40000
750 #if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)
751 #define STACK_STORE SW
752 #define STACK_LOAD LW
753 #else
754 #define STACK_STORE SD
755 #define STACK_LOAD LD
756 #endif
758 static sljit_s32 emit_op_mem(struct sljit_compiler *compiler, sljit_s32 flags, sljit_s32 reg_ar, sljit_s32 arg, sljit_sw argw);
759 static sljit_s32 emit_stack_frame_release(struct sljit_compiler *compiler, sljit_s32 frame_size, sljit_ins *ins_ptr);
761 #if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)
762 #include "sljitNativeMIPS_32.c"
763 #else
764 #include "sljitNativeMIPS_64.c"
765 #endif
767 SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_enter(struct sljit_compiler *compiler,
768 sljit_s32 options, sljit_s32 arg_types, sljit_s32 scratches, sljit_s32 saveds,
769 sljit_s32 fscratches, sljit_s32 fsaveds, sljit_s32 local_size)
771 sljit_ins base;
772 sljit_s32 i, tmp, offs;
773 sljit_s32 arg_count, word_arg_count, float_arg_count;
775 CHECK_ERROR();
776 CHECK(check_sljit_emit_enter(compiler, options, arg_types, scratches, saveds, fscratches, fsaveds, local_size));
777 set_emit_enter(compiler, options, arg_types, scratches, saveds, fscratches, fsaveds, local_size);
779 local_size += GET_SAVED_REGISTERS_SIZE(scratches, saveds, 1) + SLJIT_LOCALS_OFFSET;
780 #if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)
781 local_size = (local_size + 15) & ~0xf;
782 #else
783 local_size = (local_size + 31) & ~0x1f;
784 #endif
785 compiler->local_size = local_size;
787 if (local_size <= -SIMM_MIN) {
788 /* Frequent case. */
789 FAIL_IF(push_inst(compiler, ADDIU_W | S(SLJIT_SP) | T(SLJIT_SP) | IMM(-local_size), DR(SLJIT_SP)));
790 base = S(SLJIT_SP);
791 offs = local_size - SSIZE_OF(sw);
793 else {
794 FAIL_IF(load_immediate(compiler, DR(OTHER_FLAG), local_size));
795 FAIL_IF(push_inst(compiler, ADDU_W | S(SLJIT_SP) | TA(0) | D(TMP_REG2), DR(TMP_REG2)));
796 FAIL_IF(push_inst(compiler, SUBU_W | S(SLJIT_SP) | T(OTHER_FLAG) | D(SLJIT_SP), DR(SLJIT_SP)));
797 base = S(TMP_REG2);
798 local_size = 0;
799 offs = -(sljit_sw)sizeof(sljit_sw);
802 FAIL_IF(push_inst(compiler, STACK_STORE | base | TA(RETURN_ADDR_REG) | IMM(offs), MOVABLE_INS));
804 tmp = saveds < SLJIT_NUMBER_OF_SAVED_REGISTERS ? (SLJIT_S0 + 1 - saveds) : SLJIT_FIRST_SAVED_REG;
805 for (i = SLJIT_S0; i >= tmp; i--) {
806 offs -= (sljit_s32)(sizeof(sljit_sw));
807 FAIL_IF(push_inst(compiler, STACK_STORE | base | T(i) | IMM(offs), MOVABLE_INS));
810 for (i = scratches; i >= SLJIT_FIRST_SAVED_REG; i--) {
811 offs -= (sljit_s32)(sizeof(sljit_sw));
812 FAIL_IF(push_inst(compiler, STACK_STORE | base | T(i) | IMM(offs), MOVABLE_INS));
815 arg_types >>= SLJIT_ARG_SHIFT;
816 arg_count = 0;
817 word_arg_count = 0;
818 float_arg_count = 0;
820 #if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)
821 /* The first maximum two floating point arguments are passed in floating point
822 registers if no integer argument precedes them. The first 16 byte data is
823 passed in four integer registers, the rest is placed onto the stack.
824 The floating point registers are also part of the first 16 byte data, so
825 their corresponding integer registers are not used when they are present. */
827 while (arg_types) {
828 switch (arg_types & SLJIT_ARG_MASK) {
829 case SLJIT_ARG_TYPE_F64:
830 float_arg_count++;
831 if ((arg_count & 0x1) != 0)
832 arg_count++;
834 if (word_arg_count == 0 && float_arg_count <= 2) {
835 if (float_arg_count == 1)
836 FAIL_IF(push_inst(compiler, MOV_S | FMT_D | FS(TMP_FREG1) | FD(SLJIT_FR0), MOVABLE_INS));
837 } else if (arg_count < 4) {
838 FAIL_IF(push_inst(compiler, MTC1 | TA(4 + arg_count) | FS(float_arg_count), MOVABLE_INS));
839 FAIL_IF(push_inst(compiler, MTC1 | TA(5 + arg_count) | FS(float_arg_count) | (1 << 11), MOVABLE_INS));
840 } else
841 FAIL_IF(push_inst(compiler, LDC1 | base | FT(float_arg_count) | IMM(local_size + (arg_count << 2)), MOVABLE_INS));
842 arg_count++;
843 break;
844 case SLJIT_ARG_TYPE_F32:
845 float_arg_count++;
847 if (word_arg_count == 0 && float_arg_count <= 2) {
848 if (float_arg_count == 1)
849 FAIL_IF(push_inst(compiler, MOV_S | FMT_S | FS(TMP_FREG1) | FD(SLJIT_FR0), MOVABLE_INS));
850 } else if (arg_count < 4)
851 FAIL_IF(push_inst(compiler, MTC1 | TA(4 + arg_count) | FS(float_arg_count), MOVABLE_INS));
852 else
853 FAIL_IF(push_inst(compiler, LWC1 | base | FT(float_arg_count) | IMM(local_size + (arg_count << 2)), MOVABLE_INS));
854 break;
855 default:
856 if (arg_count < 4)
857 FAIL_IF(push_inst(compiler, ADDU_W | SA(4 + arg_count) | TA(0) | D(SLJIT_S0 - word_arg_count),
858 DR(SLJIT_S0 - word_arg_count)));
859 else
860 FAIL_IF(push_inst(compiler, LW | base | T(SLJIT_S0 - word_arg_count) | IMM(local_size + (arg_count << 2)),
861 DR(SLJIT_S0 - word_arg_count)));
862 word_arg_count++;
863 break;
865 arg_count++;
866 arg_types >>= SLJIT_ARG_SHIFT;
869 compiler->args_size = (sljit_uw)arg_count << 2;
870 #else /* !SLJIT_CONFIG_MIPS_32 */
871 while (arg_types) {
872 arg_count++;
873 switch (arg_types & SLJIT_ARG_MASK) {
874 case SLJIT_ARG_TYPE_F64:
875 float_arg_count++;
876 if (arg_count != float_arg_count)
877 FAIL_IF(push_inst(compiler, MOV_S | FMT_D | FS(arg_count) | FD(float_arg_count), MOVABLE_INS));
878 else if (arg_count == 1)
879 FAIL_IF(push_inst(compiler, MOV_S | FMT_D | FS(TMP_FREG1) | FD(SLJIT_FR0), MOVABLE_INS));
880 break;
881 case SLJIT_ARG_TYPE_F32:
882 float_arg_count++;
883 if (arg_count != float_arg_count)
884 FAIL_IF(push_inst(compiler, MOV_S | FMT_S | FS(arg_count) | FD(float_arg_count), MOVABLE_INS));
885 else if (arg_count == 1)
886 FAIL_IF(push_inst(compiler, MOV_S | FMT_S | FS(TMP_FREG1) | FD(SLJIT_FR0), MOVABLE_INS));
887 break;
888 default:
889 FAIL_IF(push_inst(compiler, ADDU_W | SA(3 + arg_count) | TA(0) | D(SLJIT_S0 - word_arg_count), DR(SLJIT_S0 - word_arg_count)));
890 word_arg_count++;
891 break;
893 arg_types >>= SLJIT_ARG_SHIFT;
895 #endif /* SLJIT_CONFIG_MIPS_32 */
897 return SLJIT_SUCCESS;
900 SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_set_context(struct sljit_compiler *compiler,
901 sljit_s32 options, sljit_s32 arg_types, sljit_s32 scratches, sljit_s32 saveds,
902 sljit_s32 fscratches, sljit_s32 fsaveds, sljit_s32 local_size)
904 CHECK_ERROR();
905 CHECK(check_sljit_set_context(compiler, options, arg_types, scratches, saveds, fscratches, fsaveds, local_size));
906 set_set_context(compiler, options, arg_types, scratches, saveds, fscratches, fsaveds, local_size);
908 local_size += GET_SAVED_REGISTERS_SIZE(scratches, saveds, 1) + SLJIT_LOCALS_OFFSET;
909 #if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)
910 compiler->local_size = (local_size + 15) & ~0xf;
911 #else
912 compiler->local_size = (local_size + 31) & ~0x1f;
913 #endif
914 return SLJIT_SUCCESS;
917 static sljit_s32 emit_stack_frame_release(struct sljit_compiler *compiler, sljit_s32 frame_size, sljit_ins *ins_ptr)
919 sljit_s32 local_size, i, tmp, offs;
921 local_size = compiler->local_size;
923 tmp = (sljit_s32)GET_SAVED_REGISTERS_SIZE(compiler->scratches, compiler->saveds, 1);
925 if (frame_size > 0) {
926 SLJIT_ASSERT(frame_size >= 2 * SSIZE_OF(sw));
927 local_size -= SSIZE_OF(sw);
928 tmp -= SSIZE_OF(sw);
929 frame_size -= SSIZE_OF(sw);
932 if (local_size <= SIMM_MAX) {
933 offs = local_size - tmp;
935 if (local_size < frame_size) {
936 offs = frame_size - tmp;
937 FAIL_IF(push_inst(compiler, ADDIU_W | S(SLJIT_SP) | T(SLJIT_SP) | IMM(local_size - frame_size), DR(SLJIT_SP)));
938 local_size = frame_size;
940 } else {
941 offs = 0;
943 if (tmp < frame_size) {
944 offs = frame_size - tmp;
945 tmp = frame_size;
948 FAIL_IF(load_immediate(compiler, DR(TMP_REG1), local_size - tmp));
949 FAIL_IF(push_inst(compiler, ADDU_W | S(SLJIT_SP) | T(TMP_REG1) | D(SLJIT_SP), DR(SLJIT_SP)));
950 local_size = tmp;
953 SLJIT_ASSERT(local_size >= frame_size);
955 if (frame_size == 0)
956 FAIL_IF(push_inst(compiler, STACK_LOAD | S(SLJIT_SP) | TA(RETURN_ADDR_REG) | IMM(local_size - SSIZE_OF(sw)), RETURN_ADDR_REG));
958 tmp = compiler->scratches;
959 for (i = SLJIT_FIRST_SAVED_REG; i <= tmp; i++) {
960 FAIL_IF(push_inst(compiler, STACK_LOAD | S(SLJIT_SP) | T(i) | IMM(offs), DR(i)));
961 offs += SSIZE_OF(sw);
964 tmp = compiler->saveds < SLJIT_NUMBER_OF_SAVED_REGISTERS ? (SLJIT_S0 + 1 - compiler->saveds) : SLJIT_FIRST_SAVED_REG;
965 for (i = tmp; i <= SLJIT_S0; i++) {
966 FAIL_IF(push_inst(compiler, STACK_LOAD | S(SLJIT_SP) | T(i) | IMM(offs), DR(i)));
967 offs += SSIZE_OF(sw);
970 SLJIT_ASSERT(offs == local_size - (frame_size == 0 ? SSIZE_OF(sw) : 0));
972 if (local_size > frame_size)
973 *ins_ptr = ADDIU_W | S(SLJIT_SP) | T(SLJIT_SP) | IMM(local_size - frame_size);
974 else
975 *ins_ptr = NOP;
977 return SLJIT_SUCCESS;
980 SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_return_void(struct sljit_compiler *compiler)
982 sljit_ins ins;
984 CHECK_ERROR();
985 CHECK(check_sljit_emit_return_void(compiler));
987 emit_stack_frame_release(compiler, 0, &ins);
989 FAIL_IF(push_inst(compiler, JR | SA(RETURN_ADDR_REG), UNMOVABLE_INS));
990 return push_inst(compiler, ins, UNMOVABLE_INS);
993 #undef STACK_STORE
994 #undef STACK_LOAD
996 /* --------------------------------------------------------------------- */
997 /* Operators */
998 /* --------------------------------------------------------------------- */
1000 #if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)
1001 #define ARCH_32_64(a, b) a
1002 #else
1003 #define ARCH_32_64(a, b) b
1004 #endif
1006 static const sljit_ins data_transfer_insts[16 + 4] = {
1007 /* u w s */ ARCH_32_64(HI(43) /* sw */, HI(63) /* sd */),
1008 /* u w l */ ARCH_32_64(HI(35) /* lw */, HI(55) /* ld */),
1009 /* u b s */ HI(40) /* sb */,
1010 /* u b l */ HI(36) /* lbu */,
1011 /* u h s */ HI(41) /* sh */,
1012 /* u h l */ HI(37) /* lhu */,
1013 /* u i s */ HI(43) /* sw */,
1014 /* u i l */ ARCH_32_64(HI(35) /* lw */, HI(39) /* lwu */),
1016 /* s w s */ ARCH_32_64(HI(43) /* sw */, HI(63) /* sd */),
1017 /* s w l */ ARCH_32_64(HI(35) /* lw */, HI(55) /* ld */),
1018 /* s b s */ HI(40) /* sb */,
1019 /* s b l */ HI(32) /* lb */,
1020 /* s h s */ HI(41) /* sh */,
1021 /* s h l */ HI(33) /* lh */,
1022 /* s i s */ HI(43) /* sw */,
1023 /* s i l */ HI(35) /* lw */,
1025 /* d s */ HI(61) /* sdc1 */,
1026 /* d l */ HI(53) /* ldc1 */,
1027 /* s s */ HI(57) /* swc1 */,
1028 /* s l */ HI(49) /* lwc1 */,
1031 #undef ARCH_32_64
1033 /* reg_ar is an absoulute register! */
1035 /* Can perform an operation using at most 1 instruction. */
1036 static sljit_s32 getput_arg_fast(struct sljit_compiler *compiler, sljit_s32 flags, sljit_s32 reg_ar, sljit_s32 arg, sljit_sw argw)
1038 SLJIT_ASSERT(arg & SLJIT_MEM);
1040 if (!(arg & OFFS_REG_MASK) && argw <= SIMM_MAX && argw >= SIMM_MIN) {
1041 /* Works for both absoulte and relative addresses. */
1042 if (SLJIT_UNLIKELY(flags & ARG_TEST))
1043 return 1;
1044 FAIL_IF(push_inst(compiler, data_transfer_insts[flags & MEM_MASK] | S(arg & REG_MASK)
1045 | TA(reg_ar) | IMM(argw), ((flags & MEM_MASK) <= GPR_REG && (flags & LOAD_DATA)) ? reg_ar : MOVABLE_INS));
1046 return -1;
1048 return 0;
1051 /* See getput_arg below.
1052 Note: can_cache is called only for binary operators. Those
1053 operators always uses word arguments without write back. */
1054 static sljit_s32 can_cache(sljit_s32 arg, sljit_sw argw, sljit_s32 next_arg, sljit_sw next_argw)
1056 SLJIT_ASSERT((arg & SLJIT_MEM) && (next_arg & SLJIT_MEM));
1058 /* Simple operation except for updates. */
1059 if (arg & OFFS_REG_MASK) {
1060 argw &= 0x3;
1061 next_argw &= 0x3;
1062 if (argw && argw == next_argw && (arg == next_arg || (arg & OFFS_REG_MASK) == (next_arg & OFFS_REG_MASK)))
1063 return 1;
1064 return 0;
1067 if (arg == next_arg) {
1068 if (((next_argw - argw) <= SIMM_MAX && (next_argw - argw) >= SIMM_MIN))
1069 return 1;
1070 return 0;
1073 return 0;
1076 /* Emit the necessary instructions. See can_cache above. */
1077 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)
1079 sljit_s32 tmp_ar, base, delay_slot;
1081 SLJIT_ASSERT(arg & SLJIT_MEM);
1082 if (!(next_arg & SLJIT_MEM)) {
1083 next_arg = 0;
1084 next_argw = 0;
1087 if ((flags & MEM_MASK) <= GPR_REG && (flags & LOAD_DATA)) {
1088 tmp_ar = reg_ar;
1089 delay_slot = reg_ar;
1091 else {
1092 tmp_ar = DR(TMP_REG1);
1093 delay_slot = MOVABLE_INS;
1095 base = arg & REG_MASK;
1097 if (SLJIT_UNLIKELY(arg & OFFS_REG_MASK)) {
1098 argw &= 0x3;
1100 /* Using the cache. */
1101 if (argw == compiler->cache_argw) {
1102 if (arg == compiler->cache_arg)
1103 return push_inst(compiler, data_transfer_insts[flags & MEM_MASK] | S(TMP_REG3) | TA(reg_ar), delay_slot);
1105 if ((SLJIT_MEM | (arg & OFFS_REG_MASK)) == compiler->cache_arg) {
1106 if (arg == next_arg && argw == (next_argw & 0x3)) {
1107 compiler->cache_arg = arg;
1108 compiler->cache_argw = argw;
1109 FAIL_IF(push_inst(compiler, ADDU_W | S(base) | T(TMP_REG3) | D(TMP_REG3), DR(TMP_REG3)));
1110 return push_inst(compiler, data_transfer_insts[flags & MEM_MASK] | S(TMP_REG3) | TA(reg_ar), delay_slot);
1112 FAIL_IF(push_inst(compiler, ADDU_W | S(base) | T(TMP_REG3) | DA(tmp_ar), tmp_ar));
1113 return push_inst(compiler, data_transfer_insts[flags & MEM_MASK] | SA(tmp_ar) | TA(reg_ar), delay_slot);
1117 if (SLJIT_UNLIKELY(argw)) {
1118 compiler->cache_arg = SLJIT_MEM | (arg & OFFS_REG_MASK);
1119 compiler->cache_argw = argw;
1120 FAIL_IF(push_inst(compiler, SLL_W | T(OFFS_REG(arg)) | D(TMP_REG3) | SH_IMM(argw), DR(TMP_REG3)));
1123 if (arg == next_arg && argw == (next_argw & 0x3)) {
1124 compiler->cache_arg = arg;
1125 compiler->cache_argw = argw;
1126 FAIL_IF(push_inst(compiler, ADDU_W | S(base) | T(!argw ? OFFS_REG(arg) : TMP_REG3) | D(TMP_REG3), DR(TMP_REG3)));
1127 tmp_ar = DR(TMP_REG3);
1129 else
1130 FAIL_IF(push_inst(compiler, ADDU_W | S(base) | T(!argw ? OFFS_REG(arg) : TMP_REG3) | DA(tmp_ar), tmp_ar));
1131 return push_inst(compiler, data_transfer_insts[flags & MEM_MASK] | SA(tmp_ar) | TA(reg_ar), delay_slot);
1134 if (compiler->cache_arg == arg && argw - compiler->cache_argw <= SIMM_MAX && argw - compiler->cache_argw >= SIMM_MIN) {
1135 if (argw != compiler->cache_argw) {
1136 FAIL_IF(push_inst(compiler, ADDIU_W | S(TMP_REG3) | T(TMP_REG3) | IMM(argw - compiler->cache_argw), DR(TMP_REG3)));
1137 compiler->cache_argw = argw;
1139 return push_inst(compiler, data_transfer_insts[flags & MEM_MASK] | S(TMP_REG3) | TA(reg_ar), delay_slot);
1142 if (compiler->cache_arg == SLJIT_MEM && argw - compiler->cache_argw <= SIMM_MAX && argw - compiler->cache_argw >= SIMM_MIN) {
1143 if (argw != compiler->cache_argw)
1144 FAIL_IF(push_inst(compiler, ADDIU_W | S(TMP_REG3) | T(TMP_REG3) | IMM(argw - compiler->cache_argw), DR(TMP_REG3)));
1146 else {
1147 compiler->cache_arg = SLJIT_MEM;
1148 FAIL_IF(load_immediate(compiler, DR(TMP_REG3), argw));
1150 compiler->cache_argw = argw;
1152 if (!base)
1153 return push_inst(compiler, data_transfer_insts[flags & MEM_MASK] | S(TMP_REG3) | TA(reg_ar), delay_slot);
1155 if (arg == next_arg && next_argw - argw <= SIMM_MAX && next_argw - argw >= SIMM_MIN) {
1156 compiler->cache_arg = arg;
1157 FAIL_IF(push_inst(compiler, ADDU_W | S(TMP_REG3) | T(base) | D(TMP_REG3), DR(TMP_REG3)));
1158 return push_inst(compiler, data_transfer_insts[flags & MEM_MASK] | S(TMP_REG3) | TA(reg_ar), delay_slot);
1161 FAIL_IF(push_inst(compiler, ADDU_W | S(TMP_REG3) | T(base) | DA(tmp_ar), tmp_ar));
1162 return push_inst(compiler, data_transfer_insts[flags & MEM_MASK] | SA(tmp_ar) | TA(reg_ar), delay_slot);
1165 static sljit_s32 emit_op_mem(struct sljit_compiler *compiler, sljit_s32 flags, sljit_s32 reg_ar, sljit_s32 arg, sljit_sw argw)
1167 sljit_s32 tmp_ar, base, delay_slot;
1169 if (getput_arg_fast(compiler, flags, reg_ar, arg, argw))
1170 return compiler->error;
1172 if ((flags & MEM_MASK) <= GPR_REG && (flags & LOAD_DATA)) {
1173 tmp_ar = reg_ar;
1174 delay_slot = reg_ar;
1176 else {
1177 tmp_ar = DR(TMP_REG1);
1178 delay_slot = MOVABLE_INS;
1180 base = arg & REG_MASK;
1182 if (SLJIT_UNLIKELY(arg & OFFS_REG_MASK)) {
1183 argw &= 0x3;
1185 if (SLJIT_UNLIKELY(argw)) {
1186 FAIL_IF(push_inst(compiler, SLL_W | T(OFFS_REG(arg)) | DA(tmp_ar) | SH_IMM(argw), tmp_ar));
1187 FAIL_IF(push_inst(compiler, ADDU_W | S(base) | TA(tmp_ar) | DA(tmp_ar), tmp_ar));
1189 else
1190 FAIL_IF(push_inst(compiler, ADDU_W | S(base) | T(OFFS_REG(arg)) | DA(tmp_ar), tmp_ar));
1191 return push_inst(compiler, data_transfer_insts[flags & MEM_MASK] | SA(tmp_ar) | TA(reg_ar), delay_slot);
1194 FAIL_IF(load_immediate(compiler, tmp_ar, argw));
1196 if (base != 0)
1197 FAIL_IF(push_inst(compiler, ADDU_W | S(base) | TA(tmp_ar) | DA(tmp_ar), tmp_ar));
1199 return push_inst(compiler, data_transfer_insts[flags & MEM_MASK] | SA(tmp_ar) | TA(reg_ar), delay_slot);
1202 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)
1204 if (getput_arg_fast(compiler, flags, reg, arg1, arg1w))
1205 return compiler->error;
1206 return getput_arg(compiler, flags, reg, arg1, arg1w, arg2, arg2w);
1209 static sljit_s32 emit_op(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 flags,
1210 sljit_s32 dst, sljit_sw dstw,
1211 sljit_s32 src1, sljit_sw src1w,
1212 sljit_s32 src2, sljit_sw src2w)
1214 /* arg1 goes to TMP_REG1 or src reg
1215 arg2 goes to TMP_REG2, imm or src reg
1216 TMP_REG3 can be used for caching
1217 result goes to TMP_REG2, so put result can use TMP_REG1 and TMP_REG3. */
1218 sljit_s32 dst_r = TMP_REG2;
1219 sljit_s32 src1_r;
1220 sljit_sw src2_r = 0;
1221 sljit_s32 sugg_src2_r = TMP_REG2;
1223 if (!(flags & ALT_KEEP_CACHE)) {
1224 compiler->cache_arg = 0;
1225 compiler->cache_argw = 0;
1228 if (dst == TMP_REG2) {
1229 SLJIT_ASSERT(HAS_FLAGS(op));
1230 flags |= UNUSED_DEST;
1232 else if (FAST_IS_REG(dst)) {
1233 dst_r = dst;
1234 flags |= REG_DEST;
1235 if (flags & MOVE_OP)
1236 sugg_src2_r = dst_r;
1238 else if ((dst & SLJIT_MEM) && !getput_arg_fast(compiler, flags | ARG_TEST, DR(TMP_REG1), dst, dstw))
1239 flags |= SLOW_DEST;
1241 if (flags & IMM_OP) {
1242 if ((src2 & SLJIT_IMM) && src2w) {
1243 if ((!(flags & LOGICAL_OP) && (src2w <= SIMM_MAX && src2w >= SIMM_MIN))
1244 || ((flags & LOGICAL_OP) && !(src2w & ~UIMM_MAX))) {
1245 flags |= SRC2_IMM;
1246 src2_r = src2w;
1249 if (!(flags & SRC2_IMM) && (flags & CUMULATIVE_OP) && (src1 & SLJIT_IMM) && src1w) {
1250 if ((!(flags & LOGICAL_OP) && (src1w <= SIMM_MAX && src1w >= SIMM_MIN))
1251 || ((flags & LOGICAL_OP) && !(src1w & ~UIMM_MAX))) {
1252 flags |= SRC2_IMM;
1253 src2_r = src1w;
1255 /* And swap arguments. */
1256 src1 = src2;
1257 src1w = src2w;
1258 src2 = SLJIT_IMM;
1259 /* src2w = src2_r unneeded. */
1264 /* Source 1. */
1265 if (FAST_IS_REG(src1)) {
1266 src1_r = src1;
1267 flags |= REG1_SOURCE;
1269 else if (src1 & SLJIT_IMM) {
1270 if (src1w) {
1271 FAIL_IF(load_immediate(compiler, DR(TMP_REG1), src1w));
1272 src1_r = TMP_REG1;
1274 else
1275 src1_r = 0;
1277 else {
1278 if (getput_arg_fast(compiler, flags | LOAD_DATA, DR(TMP_REG1), src1, src1w))
1279 FAIL_IF(compiler->error);
1280 else
1281 flags |= SLOW_SRC1;
1282 src1_r = TMP_REG1;
1285 /* Source 2. */
1286 if (FAST_IS_REG(src2)) {
1287 src2_r = src2;
1288 flags |= REG2_SOURCE;
1289 if ((flags & (REG_DEST | MOVE_OP)) == MOVE_OP)
1290 dst_r = (sljit_s32)src2_r;
1292 else if (src2 & SLJIT_IMM) {
1293 if (!(flags & SRC2_IMM)) {
1294 if (src2w) {
1295 FAIL_IF(load_immediate(compiler, DR(sugg_src2_r), src2w));
1296 src2_r = sugg_src2_r;
1298 else {
1299 src2_r = 0;
1300 if (flags & MOVE_OP) {
1301 if (dst & SLJIT_MEM)
1302 dst_r = 0;
1303 else
1304 op = SLJIT_MOV;
1309 else {
1310 if (getput_arg_fast(compiler, flags | LOAD_DATA, DR(sugg_src2_r), src2, src2w))
1311 FAIL_IF(compiler->error);
1312 else
1313 flags |= SLOW_SRC2;
1314 src2_r = sugg_src2_r;
1317 if ((flags & (SLOW_SRC1 | SLOW_SRC2)) == (SLOW_SRC1 | SLOW_SRC2)) {
1318 SLJIT_ASSERT(src2_r == TMP_REG2);
1319 if (!can_cache(src1, src1w, src2, src2w) && can_cache(src1, src1w, dst, dstw)) {
1320 FAIL_IF(getput_arg(compiler, flags | LOAD_DATA, DR(TMP_REG2), src2, src2w, src1, src1w));
1321 FAIL_IF(getput_arg(compiler, flags | LOAD_DATA, DR(TMP_REG1), src1, src1w, dst, dstw));
1323 else {
1324 FAIL_IF(getput_arg(compiler, flags | LOAD_DATA, DR(TMP_REG1), src1, src1w, src2, src2w));
1325 FAIL_IF(getput_arg(compiler, flags | LOAD_DATA, DR(TMP_REG2), src2, src2w, dst, dstw));
1328 else if (flags & SLOW_SRC1)
1329 FAIL_IF(getput_arg(compiler, flags | LOAD_DATA, DR(TMP_REG1), src1, src1w, dst, dstw));
1330 else if (flags & SLOW_SRC2)
1331 FAIL_IF(getput_arg(compiler, flags | LOAD_DATA, DR(sugg_src2_r), src2, src2w, dst, dstw));
1333 FAIL_IF(emit_single_op(compiler, op, flags, dst_r, src1_r, src2_r));
1335 if (dst & SLJIT_MEM) {
1336 if (!(flags & SLOW_DEST)) {
1337 getput_arg_fast(compiler, flags, DR(dst_r), dst, dstw);
1338 return compiler->error;
1340 return getput_arg(compiler, flags, DR(dst_r), dst, dstw, 0, 0);
1343 return SLJIT_SUCCESS;
1346 SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op0(struct sljit_compiler *compiler, sljit_s32 op)
1348 #if (defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64)
1349 sljit_s32 int_op = op & SLJIT_32;
1350 #endif
1352 CHECK_ERROR();
1353 CHECK(check_sljit_emit_op0(compiler, op));
1355 op = GET_OPCODE(op);
1356 switch (op) {
1357 case SLJIT_BREAKPOINT:
1358 return push_inst(compiler, BREAK, UNMOVABLE_INS);
1359 case SLJIT_NOP:
1360 return push_inst(compiler, NOP, UNMOVABLE_INS);
1361 case SLJIT_LMUL_UW:
1362 case SLJIT_LMUL_SW:
1363 #if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 6)
1364 #if (defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64)
1365 FAIL_IF(push_inst(compiler, (op == SLJIT_LMUL_UW ? DMULU : DMUL) | S(SLJIT_R0) | T(SLJIT_R1) | D(TMP_REG3), DR(TMP_REG3)));
1366 FAIL_IF(push_inst(compiler, (op == SLJIT_LMUL_UW ? DMUHU : DMUH) | S(SLJIT_R0) | T(SLJIT_R1) | D(TMP_REG1), DR(TMP_REG1)));
1367 #else /* !SLJIT_CONFIG_MIPS_64 */
1368 FAIL_IF(push_inst(compiler, (op == SLJIT_LMUL_UW ? MULU : MUL) | S(SLJIT_R0) | T(SLJIT_R1) | D(TMP_REG3), DR(TMP_REG3)));
1369 FAIL_IF(push_inst(compiler, (op == SLJIT_LMUL_UW ? MUHU : MUH) | S(SLJIT_R0) | T(SLJIT_R1) | D(TMP_REG1), DR(TMP_REG1)));
1370 #endif /* SLJIT_CONFIG_MIPS_64 */
1371 FAIL_IF(push_inst(compiler, ADDU_W | S(TMP_REG3) | TA(0) | D(SLJIT_R0), DR(SLJIT_R0)));
1372 return push_inst(compiler, ADDU_W | S(TMP_REG1) | TA(0) | D(SLJIT_R1), DR(SLJIT_R1));
1373 #else /* SLJIT_MIPS_REV < 6 */
1374 #if (defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64)
1375 FAIL_IF(push_inst(compiler, (op == SLJIT_LMUL_UW ? DMULTU : DMULT) | S(SLJIT_R0) | T(SLJIT_R1), MOVABLE_INS));
1376 #else /* !SLJIT_CONFIG_MIPS_64 */
1377 FAIL_IF(push_inst(compiler, (op == SLJIT_LMUL_UW ? MULTU : MULT) | S(SLJIT_R0) | T(SLJIT_R1), MOVABLE_INS));
1378 #endif /* SLJIT_CONFIG_MIPS_64 */
1379 FAIL_IF(push_inst(compiler, MFLO | D(SLJIT_R0), DR(SLJIT_R0)));
1380 return push_inst(compiler, MFHI | D(SLJIT_R1), DR(SLJIT_R1));
1381 #endif /* SLJIT_MIPS_REV >= 6 */
1382 case SLJIT_DIVMOD_UW:
1383 case SLJIT_DIVMOD_SW:
1384 case SLJIT_DIV_UW:
1385 case SLJIT_DIV_SW:
1386 SLJIT_COMPILE_ASSERT((SLJIT_DIVMOD_UW & 0x2) == 0 && SLJIT_DIV_UW - 0x2 == SLJIT_DIVMOD_UW, bad_div_opcode_assignments);
1387 #if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 6)
1388 #if (defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64)
1389 if (int_op) {
1390 FAIL_IF(push_inst(compiler, ((op | 0x2) == SLJIT_DIV_UW ? DIVU : DIV) | S(SLJIT_R0) | T(SLJIT_R1) | D(TMP_REG3), DR(TMP_REG3)));
1391 FAIL_IF(push_inst(compiler, ((op | 0x2) == SLJIT_DIV_UW ? MODU : MOD) | S(SLJIT_R0) | T(SLJIT_R1) | D(TMP_REG1), DR(TMP_REG1)));
1393 else {
1394 FAIL_IF(push_inst(compiler, ((op | 0x2) == SLJIT_DIV_UW ? DDIVU : DDIV) | S(SLJIT_R0) | T(SLJIT_R1) | D(TMP_REG3), DR(TMP_REG3)));
1395 FAIL_IF(push_inst(compiler, ((op | 0x2) == SLJIT_DIV_UW ? DMODU : DMOD) | S(SLJIT_R0) | T(SLJIT_R1) | D(TMP_REG1), DR(TMP_REG1)));
1397 #else /* !SLJIT_CONFIG_MIPS_64 */
1398 FAIL_IF(push_inst(compiler, ((op | 0x2) == SLJIT_DIV_UW ? DIVU : DIV) | S(SLJIT_R0) | T(SLJIT_R1) | D(TMP_REG3), DR(TMP_REG3)));
1399 FAIL_IF(push_inst(compiler, ((op | 0x2) == SLJIT_DIV_UW ? MODU : MOD) | S(SLJIT_R0) | T(SLJIT_R1) | D(TMP_REG1), DR(TMP_REG1)));
1400 #endif /* SLJIT_CONFIG_MIPS_64 */
1401 FAIL_IF(push_inst(compiler, ADDU_W | S(TMP_REG3) | TA(0) | D(SLJIT_R0), DR(SLJIT_R0)));
1402 return (op >= SLJIT_DIV_UW) ? SLJIT_SUCCESS : push_inst(compiler, ADDU_W | S(TMP_REG1) | TA(0) | D(SLJIT_R1), DR(SLJIT_R1));
1403 #else /* SLJIT_MIPS_REV < 6 */
1404 #if !(defined SLJIT_MIPS_REV)
1405 FAIL_IF(push_inst(compiler, NOP, UNMOVABLE_INS));
1406 FAIL_IF(push_inst(compiler, NOP, UNMOVABLE_INS));
1407 #endif /* !SLJIT_MIPS_REV */
1408 #if (defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64)
1409 if (int_op)
1410 FAIL_IF(push_inst(compiler, ((op | 0x2) == SLJIT_DIV_UW ? DIVU : DIV) | S(SLJIT_R0) | T(SLJIT_R1), MOVABLE_INS));
1411 else
1412 FAIL_IF(push_inst(compiler, ((op | 0x2) == SLJIT_DIV_UW ? DDIVU : DDIV) | S(SLJIT_R0) | T(SLJIT_R1), MOVABLE_INS));
1413 #else /* !SLJIT_CONFIG_MIPS_64 */
1414 FAIL_IF(push_inst(compiler, ((op | 0x2) == SLJIT_DIV_UW ? DIVU : DIV) | S(SLJIT_R0) | T(SLJIT_R1), MOVABLE_INS));
1415 #endif /* SLJIT_CONFIG_MIPS_64 */
1416 FAIL_IF(push_inst(compiler, MFLO | D(SLJIT_R0), DR(SLJIT_R0)));
1417 return (op >= SLJIT_DIV_UW) ? SLJIT_SUCCESS : push_inst(compiler, MFHI | D(SLJIT_R1), DR(SLJIT_R1));
1418 #endif /* SLJIT_MIPS_REV >= 6 */
1419 case SLJIT_ENDBR:
1420 case SLJIT_SKIP_FRAMES_BEFORE_RETURN:
1421 return SLJIT_SUCCESS;
1424 return SLJIT_SUCCESS;
1427 #if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 1)
1428 static sljit_s32 emit_prefetch(struct sljit_compiler *compiler,
1429 sljit_s32 src, sljit_sw srcw)
1431 if (!(src & OFFS_REG_MASK)) {
1432 if (srcw <= SIMM_MAX && srcw >= SIMM_MIN)
1433 return push_inst(compiler, PREF | S(src & REG_MASK) | IMM(srcw), MOVABLE_INS);
1435 FAIL_IF(load_immediate(compiler, DR(TMP_REG1), srcw));
1436 return push_inst(compiler, PREFX | S(src & REG_MASK) | T(TMP_REG1), MOVABLE_INS);
1439 srcw &= 0x3;
1441 if (SLJIT_UNLIKELY(srcw != 0)) {
1442 FAIL_IF(push_inst(compiler, SLL_W | T(OFFS_REG(src)) | D(TMP_REG1) | SH_IMM(srcw), DR(TMP_REG1)));
1443 return push_inst(compiler, PREFX | S(src & REG_MASK) | T(TMP_REG1), MOVABLE_INS);
1446 return push_inst(compiler, PREFX | S(src & REG_MASK) | T(OFFS_REG(src)), MOVABLE_INS);
1448 #endif /* SLJIT_MIPS_REV >= 1 */
1450 SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op1(struct sljit_compiler *compiler, sljit_s32 op,
1451 sljit_s32 dst, sljit_sw dstw,
1452 sljit_s32 src, sljit_sw srcw)
1454 sljit_s32 flags = 0;
1456 CHECK_ERROR();
1457 CHECK(check_sljit_emit_op1(compiler, op, dst, dstw, src, srcw));
1458 ADJUST_LOCAL_OFFSET(dst, dstw);
1459 ADJUST_LOCAL_OFFSET(src, srcw);
1461 #if (defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64)
1462 if (op & SLJIT_32)
1463 flags = INT_DATA | SIGNED_DATA;
1464 #endif
1466 switch (GET_OPCODE(op)) {
1467 case SLJIT_MOV:
1468 #if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)
1469 case SLJIT_MOV_U32:
1470 case SLJIT_MOV_S32:
1471 case SLJIT_MOV32:
1472 #endif
1473 case SLJIT_MOV_P:
1474 return emit_op(compiler, SLJIT_MOV, WORD_DATA | MOVE_OP, dst, dstw, TMP_REG1, 0, src, srcw);
1476 #if (defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64)
1477 case SLJIT_MOV_U32:
1478 return emit_op(compiler, SLJIT_MOV_U32, INT_DATA | MOVE_OP, dst, dstw, TMP_REG1, 0, src, (src & SLJIT_IMM) ? (sljit_u32)srcw : srcw);
1480 case SLJIT_MOV_S32:
1481 case SLJIT_MOV32:
1482 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);
1483 #endif
1485 case SLJIT_MOV_U8:
1486 return emit_op(compiler, op, BYTE_DATA | MOVE_OP, dst, dstw, TMP_REG1, 0, src, (src & SLJIT_IMM) ? (sljit_u8)srcw : srcw);
1488 case SLJIT_MOV_S8:
1489 return emit_op(compiler, op, BYTE_DATA | SIGNED_DATA | MOVE_OP, dst, dstw, TMP_REG1, 0, src, (src & SLJIT_IMM) ? (sljit_s8)srcw : srcw);
1491 case SLJIT_MOV_U16:
1492 return emit_op(compiler, op, HALF_DATA | MOVE_OP, dst, dstw, TMP_REG1, 0, src, (src & SLJIT_IMM) ? (sljit_u16)srcw : srcw);
1494 case SLJIT_MOV_S16:
1495 return emit_op(compiler, op, HALF_DATA | SIGNED_DATA | MOVE_OP, dst, dstw, TMP_REG1, 0, src, (src & SLJIT_IMM) ? (sljit_s16)srcw : srcw);
1497 case SLJIT_NOT:
1498 return emit_op(compiler, op, flags, dst, dstw, TMP_REG1, 0, src, srcw);
1500 case SLJIT_NEG:
1501 compiler->status_flags_state = SLJIT_CURRENT_FLAGS_ADD_SUB;
1502 return emit_op(compiler, SLJIT_SUB | GET_ALL_FLAGS(op), flags | IMM_OP, dst, dstw, SLJIT_IMM, 0, src, srcw);
1504 case SLJIT_CLZ:
1505 return emit_op(compiler, op, flags, dst, dstw, TMP_REG1, 0, src, srcw);
1508 SLJIT_UNREACHABLE();
1509 return SLJIT_SUCCESS;
1512 SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op2(struct sljit_compiler *compiler, sljit_s32 op,
1513 sljit_s32 dst, sljit_sw dstw,
1514 sljit_s32 src1, sljit_sw src1w,
1515 sljit_s32 src2, sljit_sw src2w)
1517 sljit_s32 flags = 0;
1519 CHECK_ERROR();
1520 CHECK(check_sljit_emit_op2(compiler, op, 0, dst, dstw, src1, src1w, src2, src2w));
1521 ADJUST_LOCAL_OFFSET(dst, dstw);
1522 ADJUST_LOCAL_OFFSET(src1, src1w);
1523 ADJUST_LOCAL_OFFSET(src2, src2w);
1525 #if (defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64)
1526 if (op & SLJIT_32) {
1527 flags |= INT_DATA | SIGNED_DATA;
1528 if (src1 & SLJIT_IMM)
1529 src1w = (sljit_s32)src1w;
1530 if (src2 & SLJIT_IMM)
1531 src2w = (sljit_s32)src2w;
1533 #endif
1535 switch (GET_OPCODE(op)) {
1536 case SLJIT_ADD:
1537 case SLJIT_ADDC:
1538 compiler->status_flags_state = SLJIT_CURRENT_FLAGS_ADD_SUB;
1539 return emit_op(compiler, op, flags | CUMULATIVE_OP | IMM_OP, dst, dstw, src1, src1w, src2, src2w);
1541 case SLJIT_SUB:
1542 case SLJIT_SUBC:
1543 compiler->status_flags_state = SLJIT_CURRENT_FLAGS_ADD_SUB;
1544 return emit_op(compiler, op, flags | IMM_OP, dst, dstw, src1, src1w, src2, src2w);
1546 case SLJIT_MUL:
1547 compiler->status_flags_state = 0;
1548 return emit_op(compiler, op, flags | CUMULATIVE_OP, dst, dstw, src1, src1w, src2, src2w);
1550 case SLJIT_AND:
1551 case SLJIT_OR:
1552 case SLJIT_XOR:
1553 return emit_op(compiler, op, flags | CUMULATIVE_OP | LOGICAL_OP | IMM_OP, dst, dstw, src1, src1w, src2, src2w);
1555 case SLJIT_SHL:
1556 case SLJIT_LSHR:
1557 case SLJIT_ASHR:
1558 #if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)
1559 if (src2 & SLJIT_IMM)
1560 src2w &= 0x1f;
1561 #else
1562 if (src2 & SLJIT_IMM) {
1563 if (op & SLJIT_32)
1564 src2w &= 0x1f;
1565 else
1566 src2w &= 0x3f;
1568 #endif
1569 return emit_op(compiler, op, flags | IMM_OP, dst, dstw, src1, src1w, src2, src2w);
1572 SLJIT_UNREACHABLE();
1573 return SLJIT_SUCCESS;
1576 SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op2u(struct sljit_compiler *compiler, sljit_s32 op,
1577 sljit_s32 src1, sljit_sw src1w,
1578 sljit_s32 src2, sljit_sw src2w)
1580 CHECK_ERROR();
1581 CHECK(check_sljit_emit_op2(compiler, op, 1, 0, 0, src1, src1w, src2, src2w));
1583 #if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) \
1584 || (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
1585 compiler->skip_checks = 1;
1586 #endif
1587 return sljit_emit_op2(compiler, op, TMP_REG2, 0, src1, src1w, src2, src2w);
1590 SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_src(struct sljit_compiler *compiler, sljit_s32 op,
1591 sljit_s32 src, sljit_sw srcw)
1593 CHECK_ERROR();
1594 CHECK(check_sljit_emit_op_src(compiler, op, src, srcw));
1595 ADJUST_LOCAL_OFFSET(src, srcw);
1597 switch (op) {
1598 case SLJIT_FAST_RETURN:
1599 if (FAST_IS_REG(src))
1600 FAIL_IF(push_inst(compiler, ADDU_W | S(src) | TA(0) | DA(RETURN_ADDR_REG), RETURN_ADDR_REG));
1601 else
1602 FAIL_IF(emit_op_mem(compiler, WORD_DATA | LOAD_DATA, RETURN_ADDR_REG, src, srcw));
1604 FAIL_IF(push_inst(compiler, JR | SA(RETURN_ADDR_REG), UNMOVABLE_INS));
1605 return push_inst(compiler, NOP, UNMOVABLE_INS);
1606 case SLJIT_SKIP_FRAMES_BEFORE_FAST_RETURN:
1607 return SLJIT_SUCCESS;
1608 case SLJIT_PREFETCH_L1:
1609 case SLJIT_PREFETCH_L2:
1610 case SLJIT_PREFETCH_L3:
1611 case SLJIT_PREFETCH_ONCE:
1612 #if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 1)
1613 return emit_prefetch(compiler, src, srcw);
1614 #else /* SLJIT_MIPS_REV < 1 */
1615 return SLJIT_SUCCESS;
1616 #endif /* SLJIT_MIPS_REV >= 1 */
1619 return SLJIT_SUCCESS;
1622 SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_get_register_index(sljit_s32 reg)
1624 CHECK_REG_INDEX(check_sljit_get_register_index(reg));
1625 return reg_map[reg];
1628 SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_get_float_register_index(sljit_s32 reg)
1630 CHECK_REG_INDEX(check_sljit_get_float_register_index(reg));
1631 return FR(reg);
1634 SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_custom(struct sljit_compiler *compiler,
1635 void *instruction, sljit_u32 size)
1637 CHECK_ERROR();
1638 CHECK(check_sljit_emit_op_custom(compiler, instruction, size));
1640 return push_inst(compiler, *(sljit_ins*)instruction, UNMOVABLE_INS);
1643 /* --------------------------------------------------------------------- */
1644 /* Floating point operators */
1645 /* --------------------------------------------------------------------- */
1647 #define FLOAT_DATA(op) (DOUBLE_DATA | ((op & SLJIT_32) >> 7))
1648 #define FMT(op) ((((sljit_ins)op & SLJIT_32) ^ SLJIT_32) << (21 - 8))
1650 static SLJIT_INLINE sljit_s32 sljit_emit_fop1_conv_sw_from_f64(struct sljit_compiler *compiler, sljit_s32 op,
1651 sljit_s32 dst, sljit_sw dstw,
1652 sljit_s32 src, sljit_sw srcw)
1654 #if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)
1655 # define flags (sljit_u32)0
1656 #else
1657 sljit_u32 flags = (GET_OPCODE(op) == SLJIT_CONV_SW_FROM_F64) << 21;
1658 #endif
1660 if (src & SLJIT_MEM) {
1661 FAIL_IF(emit_op_mem2(compiler, FLOAT_DATA(op) | LOAD_DATA, FR(TMP_FREG1), src, srcw, dst, dstw));
1662 src = TMP_FREG1;
1665 FAIL_IF(push_inst(compiler, (TRUNC_W_S ^ (flags >> 19)) | FMT(op) | FS(src) | FD(TMP_FREG1), MOVABLE_INS));
1667 if (FAST_IS_REG(dst))
1668 return push_inst(compiler, MFC1 | flags | T(dst) | FS(TMP_FREG1), MOVABLE_INS);
1670 /* Store the integer value from a VFP register. */
1671 return emit_op_mem2(compiler, flags ? DOUBLE_DATA : SINGLE_DATA, FR(TMP_FREG1), dst, dstw, 0, 0);
1673 #if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)
1674 # undef is_long
1675 #endif
1678 static SLJIT_INLINE sljit_s32 sljit_emit_fop1_conv_f64_from_sw(struct sljit_compiler *compiler, sljit_s32 op,
1679 sljit_s32 dst, sljit_sw dstw,
1680 sljit_s32 src, sljit_sw srcw)
1682 #if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)
1683 # define flags (sljit_u32)0
1684 #else
1685 sljit_u32 flags = (GET_OPCODE(op) == SLJIT_CONV_F64_FROM_SW) << 21;
1686 #endif
1688 sljit_s32 dst_r = FAST_IS_REG(dst) ? dst : TMP_FREG1;
1690 if (FAST_IS_REG(src))
1691 FAIL_IF(push_inst(compiler, MTC1 | flags | T(src) | FS(TMP_FREG1), MOVABLE_INS));
1692 else if (src & SLJIT_MEM) {
1693 /* Load the integer value into a VFP register. */
1694 FAIL_IF(emit_op_mem2(compiler, ((flags) ? DOUBLE_DATA : SINGLE_DATA) | LOAD_DATA, FR(TMP_FREG1), src, srcw, dst, dstw));
1696 else {
1697 #if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
1698 if (GET_OPCODE(op) == SLJIT_CONV_F64_FROM_S32)
1699 srcw = (sljit_s32)srcw;
1700 #endif
1701 FAIL_IF(load_immediate(compiler, DR(TMP_REG1), srcw));
1702 FAIL_IF(push_inst(compiler, MTC1 | flags | T(TMP_REG1) | FS(TMP_FREG1), MOVABLE_INS));
1705 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));
1707 if (dst & SLJIT_MEM)
1708 return emit_op_mem2(compiler, FLOAT_DATA(op), FR(TMP_FREG1), dst, dstw, 0, 0);
1709 return SLJIT_SUCCESS;
1711 #if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)
1712 # undef flags
1713 #endif
1716 static SLJIT_INLINE sljit_s32 sljit_emit_fop1_cmp(struct sljit_compiler *compiler, sljit_s32 op,
1717 sljit_s32 src1, sljit_sw src1w,
1718 sljit_s32 src2, sljit_sw src2w)
1720 sljit_ins inst;
1722 if (src1 & SLJIT_MEM) {
1723 FAIL_IF(emit_op_mem2(compiler, FLOAT_DATA(op) | LOAD_DATA, FR(TMP_FREG1), src1, src1w, src2, src2w));
1724 src1 = TMP_FREG1;
1727 if (src2 & SLJIT_MEM) {
1728 FAIL_IF(emit_op_mem2(compiler, FLOAT_DATA(op) | LOAD_DATA, FR(TMP_FREG2), src2, src2w, 0, 0));
1729 src2 = TMP_FREG2;
1732 switch (GET_FLAG_TYPE(op)) {
1733 case SLJIT_EQUAL_F64:
1734 case SLJIT_NOT_EQUAL_F64:
1735 inst = C_UEQ_S;
1736 break;
1737 case SLJIT_LESS_F64:
1738 case SLJIT_GREATER_EQUAL_F64:
1739 inst = C_ULT_S;
1740 break;
1741 case SLJIT_GREATER_F64:
1742 case SLJIT_LESS_EQUAL_F64:
1743 inst = C_ULE_S;
1744 break;
1745 default:
1746 SLJIT_ASSERT(GET_FLAG_TYPE(op) == SLJIT_UNORDERED_F64 || GET_FLAG_TYPE(op) == SLJIT_ORDERED_F64);
1747 inst = C_UN_S;
1748 break;
1750 return push_inst(compiler, inst | FMT(op) | FT(src2) | FS(src1) | C_FD, UNMOVABLE_INS);
1753 SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fop1(struct sljit_compiler *compiler, sljit_s32 op,
1754 sljit_s32 dst, sljit_sw dstw,
1755 sljit_s32 src, sljit_sw srcw)
1757 sljit_s32 dst_r;
1759 CHECK_ERROR();
1760 compiler->cache_arg = 0;
1761 compiler->cache_argw = 0;
1763 SLJIT_COMPILE_ASSERT((SLJIT_32 == 0x100) && !(DOUBLE_DATA & 0x2), float_transfer_bit_error);
1764 SELECT_FOP1_OPERATION_WITH_CHECKS(compiler, op, dst, dstw, src, srcw);
1766 if (GET_OPCODE(op) == SLJIT_CONV_F64_FROM_F32)
1767 op ^= SLJIT_32;
1769 dst_r = FAST_IS_REG(dst) ? dst : TMP_FREG1;
1771 if (src & SLJIT_MEM) {
1772 FAIL_IF(emit_op_mem2(compiler, FLOAT_DATA(op) | LOAD_DATA, FR(dst_r), src, srcw, dst, dstw));
1773 src = dst_r;
1776 switch (GET_OPCODE(op)) {
1777 case SLJIT_MOV_F64:
1778 if (src != dst_r) {
1779 if (dst_r != TMP_FREG1)
1780 FAIL_IF(push_inst(compiler, MOV_S | FMT(op) | FS(src) | FD(dst_r), MOVABLE_INS));
1781 else
1782 dst_r = src;
1784 break;
1785 case SLJIT_NEG_F64:
1786 FAIL_IF(push_inst(compiler, NEG_S | FMT(op) | FS(src) | FD(dst_r), MOVABLE_INS));
1787 break;
1788 case SLJIT_ABS_F64:
1789 FAIL_IF(push_inst(compiler, ABS_S | FMT(op) | FS(src) | FD(dst_r), MOVABLE_INS));
1790 break;
1791 case SLJIT_CONV_F64_FROM_F32:
1792 FAIL_IF(push_inst(compiler, CVT_S_S | (sljit_ins)((op & SLJIT_32) ? 1 : (1 << 21)) | FS(src) | FD(dst_r), MOVABLE_INS));
1793 op ^= SLJIT_32;
1794 break;
1797 if (dst & SLJIT_MEM)
1798 return emit_op_mem2(compiler, FLOAT_DATA(op), FR(dst_r), dst, dstw, 0, 0);
1799 return SLJIT_SUCCESS;
1802 SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fop2(struct sljit_compiler *compiler, sljit_s32 op,
1803 sljit_s32 dst, sljit_sw dstw,
1804 sljit_s32 src1, sljit_sw src1w,
1805 sljit_s32 src2, sljit_sw src2w)
1807 sljit_s32 dst_r, flags = 0;
1809 CHECK_ERROR();
1810 CHECK(check_sljit_emit_fop2(compiler, op, dst, dstw, src1, src1w, src2, src2w));
1811 ADJUST_LOCAL_OFFSET(dst, dstw);
1812 ADJUST_LOCAL_OFFSET(src1, src1w);
1813 ADJUST_LOCAL_OFFSET(src2, src2w);
1815 compiler->cache_arg = 0;
1816 compiler->cache_argw = 0;
1818 dst_r = FAST_IS_REG(dst) ? dst : TMP_FREG2;
1820 if (src1 & SLJIT_MEM) {
1821 if (getput_arg_fast(compiler, FLOAT_DATA(op) | LOAD_DATA, FR(TMP_FREG1), src1, src1w)) {
1822 FAIL_IF(compiler->error);
1823 src1 = TMP_FREG1;
1824 } else
1825 flags |= SLOW_SRC1;
1828 if (src2 & SLJIT_MEM) {
1829 if (getput_arg_fast(compiler, FLOAT_DATA(op) | LOAD_DATA, FR(TMP_FREG2), src2, src2w)) {
1830 FAIL_IF(compiler->error);
1831 src2 = TMP_FREG2;
1832 } else
1833 flags |= SLOW_SRC2;
1836 if ((flags & (SLOW_SRC1 | SLOW_SRC2)) == (SLOW_SRC1 | SLOW_SRC2)) {
1837 if (!can_cache(src1, src1w, src2, src2w) && can_cache(src1, src1w, dst, dstw)) {
1838 FAIL_IF(getput_arg(compiler, FLOAT_DATA(op) | LOAD_DATA, FR(TMP_FREG2), src2, src2w, src1, src1w));
1839 FAIL_IF(getput_arg(compiler, FLOAT_DATA(op) | LOAD_DATA, FR(TMP_FREG1), src1, src1w, dst, dstw));
1841 else {
1842 FAIL_IF(getput_arg(compiler, FLOAT_DATA(op) | LOAD_DATA, FR(TMP_FREG1), src1, src1w, src2, src2w));
1843 FAIL_IF(getput_arg(compiler, FLOAT_DATA(op) | LOAD_DATA, FR(TMP_FREG2), src2, src2w, dst, dstw));
1846 else if (flags & SLOW_SRC1)
1847 FAIL_IF(getput_arg(compiler, FLOAT_DATA(op) | LOAD_DATA, FR(TMP_FREG1), src1, src1w, dst, dstw));
1848 else if (flags & SLOW_SRC2)
1849 FAIL_IF(getput_arg(compiler, FLOAT_DATA(op) | LOAD_DATA, FR(TMP_FREG2), src2, src2w, dst, dstw));
1851 if (flags & SLOW_SRC1)
1852 src1 = TMP_FREG1;
1853 if (flags & SLOW_SRC2)
1854 src2 = TMP_FREG2;
1856 switch (GET_OPCODE(op)) {
1857 case SLJIT_ADD_F64:
1858 FAIL_IF(push_inst(compiler, ADD_S | FMT(op) | FT(src2) | FS(src1) | FD(dst_r), MOVABLE_INS));
1859 break;
1861 case SLJIT_SUB_F64:
1862 FAIL_IF(push_inst(compiler, SUB_S | FMT(op) | FT(src2) | FS(src1) | FD(dst_r), MOVABLE_INS));
1863 break;
1865 case SLJIT_MUL_F64:
1866 FAIL_IF(push_inst(compiler, MUL_S | FMT(op) | FT(src2) | FS(src1) | FD(dst_r), MOVABLE_INS));
1867 break;
1869 case SLJIT_DIV_F64:
1870 FAIL_IF(push_inst(compiler, DIV_S | FMT(op) | FT(src2) | FS(src1) | FD(dst_r), MOVABLE_INS));
1871 break;
1874 if (dst_r == TMP_FREG2)
1875 FAIL_IF(emit_op_mem2(compiler, FLOAT_DATA(op), FR(TMP_FREG2), dst, dstw, 0, 0));
1877 return SLJIT_SUCCESS;
1880 /* --------------------------------------------------------------------- */
1881 /* Other instructions */
1882 /* --------------------------------------------------------------------- */
1884 SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fast_enter(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw dstw)
1886 CHECK_ERROR();
1887 CHECK(check_sljit_emit_fast_enter(compiler, dst, dstw));
1888 ADJUST_LOCAL_OFFSET(dst, dstw);
1890 if (FAST_IS_REG(dst))
1891 return push_inst(compiler, ADDU_W | SA(RETURN_ADDR_REG) | TA(0) | D(dst), UNMOVABLE_INS);
1893 /* Memory. */
1894 FAIL_IF(emit_op_mem(compiler, WORD_DATA, RETURN_ADDR_REG, dst, dstw));
1895 compiler->delay_slot = UNMOVABLE_INS;
1896 return SLJIT_SUCCESS;
1899 /* --------------------------------------------------------------------- */
1900 /* Conditional instructions */
1901 /* --------------------------------------------------------------------- */
1903 SLJIT_API_FUNC_ATTRIBUTE struct sljit_label* sljit_emit_label(struct sljit_compiler *compiler)
1905 struct sljit_label *label;
1907 CHECK_ERROR_PTR();
1908 CHECK_PTR(check_sljit_emit_label(compiler));
1910 if (compiler->last_label && compiler->last_label->size == compiler->size)
1911 return compiler->last_label;
1913 label = (struct sljit_label*)ensure_abuf(compiler, sizeof(struct sljit_label));
1914 PTR_FAIL_IF(!label);
1915 set_label(label, compiler);
1916 compiler->delay_slot = UNMOVABLE_INS;
1917 return label;
1920 #if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)
1921 #define JUMP_LENGTH 4
1922 #else
1923 #define JUMP_LENGTH 8
1924 #endif
1926 #define BR_Z(src) \
1927 inst = BEQ | SA(src) | TA(0) | JUMP_LENGTH; \
1928 flags = IS_BIT26_COND; \
1929 delay_check = src;
1931 #define BR_NZ(src) \
1932 inst = BNE | SA(src) | TA(0) | JUMP_LENGTH; \
1933 flags = IS_BIT26_COND; \
1934 delay_check = src;
1936 #if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 6)
1938 #define BR_T() \
1939 inst = BC1NEZ; \
1940 flags = IS_BIT23_COND; \
1941 delay_check = FCSR_FCC;
1942 #define BR_F() \
1943 inst = BC1EQZ; \
1944 flags = IS_BIT23_COND; \
1945 delay_check = FCSR_FCC;
1947 #else /* SLJIT_MIPS_REV < 6 */
1949 #define BR_T() \
1950 inst = BC1T | JUMP_LENGTH; \
1951 flags = IS_BIT16_COND; \
1952 delay_check = FCSR_FCC;
1953 #define BR_F() \
1954 inst = BC1F | JUMP_LENGTH; \
1955 flags = IS_BIT16_COND; \
1956 delay_check = FCSR_FCC;
1958 #endif /* SLJIT_MIPS_REV >= 6 */
1960 SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_jump(struct sljit_compiler *compiler, sljit_s32 type)
1962 struct sljit_jump *jump;
1963 sljit_ins inst;
1964 sljit_u32 flags = 0;
1965 sljit_s32 delay_check = UNMOVABLE_INS;
1967 CHECK_ERROR_PTR();
1968 CHECK_PTR(check_sljit_emit_jump(compiler, type));
1970 jump = (struct sljit_jump*)ensure_abuf(compiler, sizeof(struct sljit_jump));
1971 PTR_FAIL_IF(!jump);
1972 set_jump(jump, compiler, type & SLJIT_REWRITABLE_JUMP);
1973 type &= 0xff;
1975 switch (type) {
1976 case SLJIT_EQUAL:
1977 BR_NZ(EQUAL_FLAG);
1978 break;
1979 case SLJIT_NOT_EQUAL:
1980 BR_Z(EQUAL_FLAG);
1981 break;
1982 case SLJIT_LESS:
1983 case SLJIT_GREATER:
1984 case SLJIT_SIG_LESS:
1985 case SLJIT_SIG_GREATER:
1986 case SLJIT_OVERFLOW:
1987 BR_Z(OTHER_FLAG);
1988 break;
1989 case SLJIT_GREATER_EQUAL:
1990 case SLJIT_LESS_EQUAL:
1991 case SLJIT_SIG_GREATER_EQUAL:
1992 case SLJIT_SIG_LESS_EQUAL:
1993 case SLJIT_NOT_OVERFLOW:
1994 BR_NZ(OTHER_FLAG);
1995 break;
1996 case SLJIT_NOT_EQUAL_F64:
1997 case SLJIT_GREATER_EQUAL_F64:
1998 case SLJIT_GREATER_F64:
1999 case SLJIT_ORDERED_F64:
2000 BR_T();
2001 break;
2002 case SLJIT_EQUAL_F64:
2003 case SLJIT_LESS_F64:
2004 case SLJIT_LESS_EQUAL_F64:
2005 case SLJIT_UNORDERED_F64:
2006 BR_F();
2007 break;
2008 default:
2009 /* Not conditional branch. */
2010 inst = 0;
2011 break;
2014 jump->flags |= flags;
2015 if (compiler->delay_slot == MOVABLE_INS || (compiler->delay_slot != UNMOVABLE_INS && compiler->delay_slot != delay_check))
2016 jump->flags |= IS_MOVABLE;
2018 if (inst)
2019 PTR_FAIL_IF(push_inst(compiler, inst, UNMOVABLE_INS));
2021 PTR_FAIL_IF(emit_const(compiler, TMP_REG2, 0));
2023 if (type <= SLJIT_JUMP)
2024 PTR_FAIL_IF(push_inst(compiler, JR | S(TMP_REG2), UNMOVABLE_INS));
2025 else {
2026 jump->flags |= IS_JAL;
2027 PTR_FAIL_IF(push_inst(compiler, JALR | S(TMP_REG2) | DA(RETURN_ADDR_REG), UNMOVABLE_INS));
2030 jump->addr = compiler->size;
2031 PTR_FAIL_IF(push_inst(compiler, NOP, UNMOVABLE_INS));
2032 return jump;
2035 #define RESOLVE_IMM1() \
2036 if (src1 & SLJIT_IMM) { \
2037 if (src1w) { \
2038 PTR_FAIL_IF(load_immediate(compiler, DR(TMP_REG1), src1w)); \
2039 src1 = TMP_REG1; \
2041 else \
2042 src1 = 0; \
2045 #define RESOLVE_IMM2() \
2046 if (src2 & SLJIT_IMM) { \
2047 if (src2w) { \
2048 PTR_FAIL_IF(load_immediate(compiler, DR(TMP_REG2), src2w)); \
2049 src2 = TMP_REG2; \
2051 else \
2052 src2 = 0; \
2055 SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_cmp(struct sljit_compiler *compiler, sljit_s32 type,
2056 sljit_s32 src1, sljit_sw src1w,
2057 sljit_s32 src2, sljit_sw src2w)
2059 struct sljit_jump *jump;
2060 sljit_s32 flags;
2061 sljit_ins inst;
2063 CHECK_ERROR_PTR();
2064 CHECK_PTR(check_sljit_emit_cmp(compiler, type, src1, src1w, src2, src2w));
2065 ADJUST_LOCAL_OFFSET(src1, src1w);
2066 ADJUST_LOCAL_OFFSET(src2, src2w);
2068 compiler->cache_arg = 0;
2069 compiler->cache_argw = 0;
2070 flags = ((type & SLJIT_32) ? INT_DATA : WORD_DATA) | LOAD_DATA;
2071 if (src1 & SLJIT_MEM) {
2072 PTR_FAIL_IF(emit_op_mem2(compiler, flags, DR(TMP_REG1), src1, src1w, src2, src2w));
2073 src1 = TMP_REG1;
2075 if (src2 & SLJIT_MEM) {
2076 PTR_FAIL_IF(emit_op_mem2(compiler, flags, DR(TMP_REG2), src2, src2w, 0, 0));
2077 src2 = TMP_REG2;
2080 jump = (struct sljit_jump*)ensure_abuf(compiler, sizeof(struct sljit_jump));
2081 PTR_FAIL_IF(!jump);
2082 set_jump(jump, compiler, type & SLJIT_REWRITABLE_JUMP);
2083 type &= 0xff;
2085 if (type <= SLJIT_NOT_EQUAL) {
2086 RESOLVE_IMM1();
2087 RESOLVE_IMM2();
2088 jump->flags |= IS_BIT26_COND;
2089 if (compiler->delay_slot == MOVABLE_INS || (compiler->delay_slot != UNMOVABLE_INS && compiler->delay_slot != DR(src1) && compiler->delay_slot != DR(src2)))
2090 jump->flags |= IS_MOVABLE;
2091 PTR_FAIL_IF(push_inst(compiler, (type == SLJIT_EQUAL ? BNE : BEQ) | S(src1) | T(src2) | JUMP_LENGTH, UNMOVABLE_INS));
2093 else if (type >= SLJIT_SIG_LESS && (((src1 & SLJIT_IMM) && (src1w == 0)) || ((src2 & SLJIT_IMM) && (src2w == 0)))) {
2094 inst = NOP;
2095 if ((src1 & SLJIT_IMM) && (src1w == 0)) {
2096 RESOLVE_IMM2();
2097 switch (type) {
2098 case SLJIT_SIG_LESS:
2099 inst = BLEZ;
2100 jump->flags |= IS_BIT26_COND;
2101 break;
2102 case SLJIT_SIG_GREATER_EQUAL:
2103 inst = BGTZ;
2104 jump->flags |= IS_BIT26_COND;
2105 break;
2106 case SLJIT_SIG_GREATER:
2107 inst = BGEZ;
2108 jump->flags |= IS_BIT16_COND;
2109 break;
2110 case SLJIT_SIG_LESS_EQUAL:
2111 inst = BLTZ;
2112 jump->flags |= IS_BIT16_COND;
2113 break;
2115 src1 = src2;
2117 else {
2118 RESOLVE_IMM1();
2119 switch (type) {
2120 case SLJIT_SIG_LESS:
2121 inst = BGEZ;
2122 jump->flags |= IS_BIT16_COND;
2123 break;
2124 case SLJIT_SIG_GREATER_EQUAL:
2125 inst = BLTZ;
2126 jump->flags |= IS_BIT16_COND;
2127 break;
2128 case SLJIT_SIG_GREATER:
2129 inst = BLEZ;
2130 jump->flags |= IS_BIT26_COND;
2131 break;
2132 case SLJIT_SIG_LESS_EQUAL:
2133 inst = BGTZ;
2134 jump->flags |= IS_BIT26_COND;
2135 break;
2138 PTR_FAIL_IF(push_inst(compiler, inst | S(src1) | JUMP_LENGTH, UNMOVABLE_INS));
2140 else {
2141 if (type == SLJIT_LESS || type == SLJIT_GREATER_EQUAL || type == SLJIT_SIG_LESS || type == SLJIT_SIG_GREATER_EQUAL) {
2142 RESOLVE_IMM1();
2143 if ((src2 & SLJIT_IMM) && src2w <= SIMM_MAX && src2w >= SIMM_MIN)
2144 PTR_FAIL_IF(push_inst(compiler, (type <= SLJIT_LESS_EQUAL ? SLTIU : SLTI) | S(src1) | T(TMP_REG1) | IMM(src2w), DR(TMP_REG1)));
2145 else {
2146 RESOLVE_IMM2();
2147 PTR_FAIL_IF(push_inst(compiler, (type <= SLJIT_LESS_EQUAL ? SLTU : SLT) | S(src1) | T(src2) | D(TMP_REG1), DR(TMP_REG1)));
2149 type = (type == SLJIT_LESS || type == SLJIT_SIG_LESS) ? SLJIT_NOT_EQUAL : SLJIT_EQUAL;
2151 else {
2152 RESOLVE_IMM2();
2153 if ((src1 & SLJIT_IMM) && src1w <= SIMM_MAX && src1w >= SIMM_MIN)
2154 PTR_FAIL_IF(push_inst(compiler, (type <= SLJIT_LESS_EQUAL ? SLTIU : SLTI) | S(src2) | T(TMP_REG1) | IMM(src1w), DR(TMP_REG1)));
2155 else {
2156 RESOLVE_IMM1();
2157 PTR_FAIL_IF(push_inst(compiler, (type <= SLJIT_LESS_EQUAL ? SLTU : SLT) | S(src2) | T(src1) | D(TMP_REG1), DR(TMP_REG1)));
2159 type = (type == SLJIT_GREATER || type == SLJIT_SIG_GREATER) ? SLJIT_NOT_EQUAL : SLJIT_EQUAL;
2162 jump->flags |= IS_BIT26_COND;
2163 PTR_FAIL_IF(push_inst(compiler, (type == SLJIT_EQUAL ? BNE : BEQ) | S(TMP_REG1) | TA(0) | JUMP_LENGTH, UNMOVABLE_INS));
2166 PTR_FAIL_IF(emit_const(compiler, TMP_REG2, 0));
2167 PTR_FAIL_IF(push_inst(compiler, JR | S(TMP_REG2), UNMOVABLE_INS));
2168 jump->addr = compiler->size;
2169 PTR_FAIL_IF(push_inst(compiler, NOP, UNMOVABLE_INS));
2170 return jump;
2173 #undef RESOLVE_IMM1
2174 #undef RESOLVE_IMM2
2176 #undef JUMP_LENGTH
2177 #undef BR_Z
2178 #undef BR_NZ
2179 #undef BR_T
2180 #undef BR_F
2182 #undef FLOAT_DATA
2183 #undef FMT
2185 SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_ijump(struct sljit_compiler *compiler, sljit_s32 type, sljit_s32 src, sljit_sw srcw)
2187 struct sljit_jump *jump = NULL;
2189 CHECK_ERROR();
2190 CHECK(check_sljit_emit_ijump(compiler, type, src, srcw));
2191 ADJUST_LOCAL_OFFSET(src, srcw);
2193 if (src & SLJIT_IMM) {
2194 jump = (struct sljit_jump*)ensure_abuf(compiler, sizeof(struct sljit_jump));
2195 FAIL_IF(!jump);
2196 set_jump(jump, compiler, JUMP_ADDR | ((type >= SLJIT_FAST_CALL) ? IS_JAL : 0));
2197 jump->u.target = (sljit_uw)srcw;
2199 if (compiler->delay_slot != UNMOVABLE_INS)
2200 jump->flags |= IS_MOVABLE;
2202 FAIL_IF(emit_const(compiler, TMP_REG2, 0));
2203 src = TMP_REG2;
2205 else if (src & SLJIT_MEM) {
2206 FAIL_IF(emit_op_mem(compiler, WORD_DATA | LOAD_DATA, DR(TMP_REG2), src, srcw));
2207 src = TMP_REG2;
2210 FAIL_IF(push_inst(compiler, JR | S(src), UNMOVABLE_INS));
2211 if (jump)
2212 jump->addr = compiler->size;
2213 FAIL_IF(push_inst(compiler, NOP, UNMOVABLE_INS));
2214 return SLJIT_SUCCESS;
2217 SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_flags(struct sljit_compiler *compiler, sljit_s32 op,
2218 sljit_s32 dst, sljit_sw dstw,
2219 sljit_s32 type)
2221 sljit_s32 src_ar, dst_ar;
2222 sljit_s32 saved_op = op;
2223 #if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)
2224 sljit_s32 mem_type = WORD_DATA;
2225 #else
2226 sljit_s32 mem_type = ((op & SLJIT_32) || op == SLJIT_MOV32) ? (INT_DATA | SIGNED_DATA) : WORD_DATA;
2227 #endif
2229 CHECK_ERROR();
2230 CHECK(check_sljit_emit_op_flags(compiler, op, dst, dstw, type));
2231 ADJUST_LOCAL_OFFSET(dst, dstw);
2233 op = GET_OPCODE(op);
2234 dst_ar = DR((op < SLJIT_ADD && FAST_IS_REG(dst)) ? dst : TMP_REG2);
2236 compiler->cache_arg = 0;
2237 compiler->cache_argw = 0;
2239 if (op >= SLJIT_ADD && (dst & SLJIT_MEM))
2240 FAIL_IF(emit_op_mem2(compiler, mem_type | LOAD_DATA, DR(TMP_REG1), dst, dstw, dst, dstw));
2242 switch (type & 0xff) {
2243 case SLJIT_EQUAL:
2244 case SLJIT_NOT_EQUAL:
2245 FAIL_IF(push_inst(compiler, SLTIU | SA(EQUAL_FLAG) | TA(dst_ar) | IMM(1), dst_ar));
2246 src_ar = dst_ar;
2247 break;
2248 case SLJIT_OVERFLOW:
2249 case SLJIT_NOT_OVERFLOW:
2250 if (compiler->status_flags_state & SLJIT_CURRENT_FLAGS_ADD_SUB) {
2251 src_ar = OTHER_FLAG;
2252 break;
2254 FAIL_IF(push_inst(compiler, SLTIU | SA(OTHER_FLAG) | TA(dst_ar) | IMM(1), dst_ar));
2255 src_ar = dst_ar;
2256 type ^= 0x1; /* Flip type bit for the XORI below. */
2257 break;
2258 case SLJIT_GREATER_F64:
2259 case SLJIT_LESS_EQUAL_F64:
2260 type ^= 0x1; /* Flip type bit for the XORI below. */
2261 case SLJIT_EQUAL_F64:
2262 case SLJIT_NOT_EQUAL_F64:
2263 case SLJIT_LESS_F64:
2264 case SLJIT_GREATER_EQUAL_F64:
2265 case SLJIT_UNORDERED_F64:
2266 case SLJIT_ORDERED_F64:
2267 #if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 6)
2268 FAIL_IF(push_inst(compiler, MFC1 | TA(dst_ar) | FS(TMP_FREG3), dst_ar));
2269 #else /* SLJIT_MIPS_REV < 6 */
2270 FAIL_IF(push_inst(compiler, CFC1 | TA(dst_ar) | DA(FCSR_REG), dst_ar));
2271 #endif /* SLJIT_MIPS_REV >= 6 */
2272 FAIL_IF(push_inst(compiler, SRL | TA(dst_ar) | DA(dst_ar) | SH_IMM(23), dst_ar));
2273 FAIL_IF(push_inst(compiler, ANDI | SA(dst_ar) | TA(dst_ar) | IMM(1), dst_ar));
2274 src_ar = dst_ar;
2275 break;
2277 default:
2278 src_ar = OTHER_FLAG;
2279 break;
2282 if (type & 0x1) {
2283 FAIL_IF(push_inst(compiler, XORI | SA(src_ar) | TA(dst_ar) | IMM(1), dst_ar));
2284 src_ar = dst_ar;
2287 if (op < SLJIT_ADD) {
2288 if (dst & SLJIT_MEM)
2289 return emit_op_mem(compiler, mem_type, src_ar, dst, dstw);
2291 if (src_ar != dst_ar)
2292 return push_inst(compiler, ADDU_W | SA(src_ar) | TA(0) | DA(dst_ar), dst_ar);
2293 return SLJIT_SUCCESS;
2296 /* OTHER_FLAG cannot be specified as src2 argument at the moment. */
2297 if (DR(TMP_REG2) != src_ar)
2298 FAIL_IF(push_inst(compiler, ADDU_W | SA(src_ar) | TA(0) | D(TMP_REG2), DR(TMP_REG2)));
2300 mem_type |= CUMULATIVE_OP | LOGICAL_OP | IMM_OP | ALT_KEEP_CACHE;
2302 if (dst & SLJIT_MEM)
2303 return emit_op(compiler, saved_op, mem_type, dst, dstw, TMP_REG1, 0, TMP_REG2, 0);
2304 return emit_op(compiler, saved_op, mem_type, dst, dstw, dst, dstw, TMP_REG2, 0);
2307 SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_cmov(struct sljit_compiler *compiler, sljit_s32 type,
2308 sljit_s32 dst_reg,
2309 sljit_s32 src, sljit_sw srcw)
2311 #if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 1 && SLJIT_MIPS_REV < 6)
2312 sljit_ins ins;
2313 #endif /* SLJIT_MIPS_REV >= 1 && SLJIT_MIPS_REV < 6 */
2315 CHECK_ERROR();
2316 CHECK(check_sljit_emit_cmov(compiler, type, dst_reg, src, srcw));
2318 #if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 1 && SLJIT_MIPS_REV < 6)
2320 if (SLJIT_UNLIKELY(src & SLJIT_IMM)) {
2321 #if (defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64)
2322 if (dst_reg & SLJIT_32)
2323 srcw = (sljit_s32)srcw;
2324 #endif
2325 FAIL_IF(load_immediate(compiler, DR(TMP_REG1), srcw));
2326 src = TMP_REG1;
2327 srcw = 0;
2330 dst_reg &= ~SLJIT_32;
2332 switch (type & 0xff) {
2333 case SLJIT_EQUAL:
2334 ins = MOVZ | TA(EQUAL_FLAG);
2335 break;
2336 case SLJIT_NOT_EQUAL:
2337 ins = MOVN | TA(EQUAL_FLAG);
2338 break;
2339 case SLJIT_LESS:
2340 case SLJIT_GREATER:
2341 case SLJIT_SIG_LESS:
2342 case SLJIT_SIG_GREATER:
2343 case SLJIT_OVERFLOW:
2344 ins = MOVN | TA(OTHER_FLAG);
2345 break;
2346 case SLJIT_GREATER_EQUAL:
2347 case SLJIT_LESS_EQUAL:
2348 case SLJIT_SIG_GREATER_EQUAL:
2349 case SLJIT_SIG_LESS_EQUAL:
2350 case SLJIT_NOT_OVERFLOW:
2351 ins = MOVZ | TA(OTHER_FLAG);
2352 break;
2353 case SLJIT_EQUAL_F64:
2354 case SLJIT_LESS_F64:
2355 case SLJIT_LESS_EQUAL_F64:
2356 case SLJIT_UNORDERED_F64:
2357 ins = MOVT;
2358 break;
2359 case SLJIT_NOT_EQUAL_F64:
2360 case SLJIT_GREATER_EQUAL_F64:
2361 case SLJIT_GREATER_F64:
2362 case SLJIT_ORDERED_F64:
2363 ins = MOVF;
2364 break;
2365 default:
2366 ins = MOVZ | TA(OTHER_FLAG);
2367 SLJIT_UNREACHABLE();
2368 break;
2371 return push_inst(compiler, ins | S(src) | D(dst_reg), DR(dst_reg));
2373 #else /* SLJIT_MIPS_REV < 1 || SLJIT_MIPS_REV >= 6 */
2374 return sljit_emit_cmov_generic(compiler, type, dst_reg, src, srcw);
2375 #endif /* SLJIT_MIPS_REV >= 1 */
2378 SLJIT_API_FUNC_ATTRIBUTE struct sljit_const* sljit_emit_const(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw dstw, sljit_sw init_value)
2380 struct sljit_const *const_;
2381 sljit_s32 dst_r;
2383 CHECK_ERROR_PTR();
2384 CHECK_PTR(check_sljit_emit_const(compiler, dst, dstw, init_value));
2385 ADJUST_LOCAL_OFFSET(dst, dstw);
2387 const_ = (struct sljit_const*)ensure_abuf(compiler, sizeof(struct sljit_const));
2388 PTR_FAIL_IF(!const_);
2389 set_const(const_, compiler);
2391 dst_r = FAST_IS_REG(dst) ? dst : TMP_REG2;
2392 PTR_FAIL_IF(emit_const(compiler, dst_r, init_value));
2394 if (dst & SLJIT_MEM)
2395 PTR_FAIL_IF(emit_op(compiler, SLJIT_MOV, WORD_DATA, dst, dstw, TMP_REG1, 0, TMP_REG2, 0));
2397 return const_;
2400 SLJIT_API_FUNC_ATTRIBUTE struct sljit_put_label* sljit_emit_put_label(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw dstw)
2402 struct sljit_put_label *put_label;
2403 sljit_s32 dst_r;
2405 CHECK_ERROR_PTR();
2406 CHECK_PTR(check_sljit_emit_put_label(compiler, dst, dstw));
2407 ADJUST_LOCAL_OFFSET(dst, dstw);
2409 put_label = (struct sljit_put_label*)ensure_abuf(compiler, sizeof(struct sljit_put_label));
2410 PTR_FAIL_IF(!put_label);
2411 set_put_label(put_label, compiler, 0);
2413 dst_r = FAST_IS_REG(dst) ? dst : TMP_REG2;
2414 #if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)
2415 PTR_FAIL_IF(emit_const(compiler, dst_r, 0));
2416 #else
2417 PTR_FAIL_IF(push_inst(compiler, (sljit_ins)dst_r, UNMOVABLE_INS));
2418 compiler->size += 5;
2419 #endif
2421 if (dst & SLJIT_MEM)
2422 PTR_FAIL_IF(emit_op(compiler, SLJIT_MOV, WORD_DATA, dst, dstw, TMP_REG1, 0, TMP_REG2, 0));
2424 return put_label;