Swap f32 and f64 argument types.
[sljit.git] / sljit_src / sljitNativeMIPS_common.c
blob17a48dea65ae7dd337093cc2bb0b7b5f10bf1ab6
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) (reg_map[s] << 21)
105 #define T(t) (reg_map[t] << 16)
106 #define D(d) (reg_map[d] << 11)
107 #define FT(t) (freg_map[t] << 16)
108 #define FS(s) (freg_map[s] << 11)
109 #define FD(d) (freg_map[d] << 6)
110 /* Absolute registers. */
111 #define SA(s) ((s) << 21)
112 #define TA(t) ((t) << 16)
113 #define DA(d) ((d) << 11)
114 #define IMM(imm) ((imm) & 0xffff)
115 #define SH_IMM(imm) ((imm) << 6)
117 #define DR(dr) (reg_map[dr])
118 #define FR(dr) (freg_map[dr])
119 #define HI(opcode) ((opcode) << 26)
120 #define LO(opcode) (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 || delay_slot == ((ins >> 11) & 0x1f) || delay_slot == ((ins >> 16) & 0x1f));
299 FAIL_IF(!ptr);
300 *ptr = ins;
301 compiler->size++;
302 compiler->delay_slot = delay_slot;
303 return SLJIT_SUCCESS;
306 static SLJIT_INLINE sljit_ins invert_branch(sljit_s32 flags)
308 if (flags & IS_BIT26_COND)
309 return (1 << 26);
310 #if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 6)
311 if (flags & IS_BIT23_COND)
312 return (1 << 23);
313 #endif /* SLJIT_MIPS_REV >= 6 */
314 return (1 << 16);
317 static SLJIT_INLINE sljit_ins* detect_jump_type(struct sljit_jump *jump, sljit_ins *code_ptr, sljit_ins *code, sljit_sw executable_offset)
319 sljit_sw diff;
320 sljit_uw target_addr;
321 sljit_ins *inst;
322 sljit_ins saved_inst;
324 #if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)
325 if (jump->flags & (SLJIT_REWRITABLE_JUMP | IS_CALL))
326 return code_ptr;
327 #else
328 if (jump->flags & SLJIT_REWRITABLE_JUMP)
329 return code_ptr;
330 #endif
332 if (jump->flags & JUMP_ADDR)
333 target_addr = jump->u.target;
334 else {
335 SLJIT_ASSERT(jump->flags & JUMP_LABEL);
336 target_addr = (sljit_uw)(code + jump->u.label->size) + (sljit_uw)executable_offset;
339 inst = (sljit_ins *)jump->addr;
340 if (jump->flags & IS_COND)
341 inst--;
343 #if (defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64)
344 if (jump->flags & IS_CALL)
345 goto keep_address;
346 #endif
348 /* B instructions. */
349 if (jump->flags & IS_MOVABLE) {
350 diff = ((sljit_sw)target_addr - (sljit_sw)inst - executable_offset) >> 2;
351 if (diff <= SIMM_MAX && diff >= SIMM_MIN) {
352 jump->flags |= PATCH_B;
354 if (!(jump->flags & IS_COND)) {
355 inst[0] = inst[-1];
356 inst[-1] = (jump->flags & IS_JAL) ? BAL : B;
357 jump->addr -= sizeof(sljit_ins);
358 return inst;
360 saved_inst = inst[0];
361 inst[0] = inst[-1];
362 inst[-1] = saved_inst ^ invert_branch(jump->flags);
363 jump->addr -= 2 * sizeof(sljit_ins);
364 return inst;
367 else {
368 diff = ((sljit_sw)target_addr - (sljit_sw)(inst + 1) - 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] = (jump->flags & IS_JAL) ? BAL : B;
374 inst[1] = NOP;
375 return inst + 1;
377 inst[0] = inst[0] ^ invert_branch(jump->flags);
378 inst[1] = NOP;
379 jump->addr -= sizeof(sljit_ins);
380 return inst + 1;
384 if (jump->flags & IS_COND) {
385 if ((jump->flags & IS_MOVABLE) && (target_addr & ~0xfffffff) == ((jump->addr + 2 * sizeof(sljit_ins)) & ~0xfffffff)) {
386 jump->flags |= PATCH_J;
387 saved_inst = inst[0];
388 inst[0] = inst[-1];
389 inst[-1] = (saved_inst & 0xffff0000) | 3;
390 inst[1] = J;
391 inst[2] = NOP;
392 return inst + 2;
394 else if ((target_addr & ~0xfffffff) == ((jump->addr + 3 * sizeof(sljit_ins)) & ~0xfffffff)) {
395 jump->flags |= PATCH_J;
396 inst[0] = (inst[0] & 0xffff0000) | 3;
397 inst[1] = NOP;
398 inst[2] = J;
399 inst[3] = NOP;
400 jump->addr += sizeof(sljit_ins);
401 return inst + 3;
404 else {
405 /* J instuctions. */
406 if ((jump->flags & IS_MOVABLE) && (target_addr & ~0xfffffff) == (jump->addr & ~0xfffffff)) {
407 jump->flags |= PATCH_J;
408 inst[0] = inst[-1];
409 inst[-1] = (jump->flags & IS_JAL) ? JAL : J;
410 jump->addr -= sizeof(sljit_ins);
411 return inst;
414 if ((target_addr & ~0xfffffff) == ((jump->addr + sizeof(sljit_ins)) & ~0xfffffff)) {
415 jump->flags |= PATCH_J;
416 inst[0] = (jump->flags & IS_JAL) ? JAL : J;
417 inst[1] = NOP;
418 return inst + 1;
422 #if (defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64)
423 keep_address:
424 if (target_addr <= 0x7fffffff) {
425 jump->flags |= PATCH_ABS32;
426 if (jump->flags & IS_COND) {
427 inst[0] -= 4;
428 inst++;
430 inst[2] = inst[6];
431 inst[3] = inst[7];
432 return inst + 3;
434 if (target_addr <= 0x7fffffffffffl) {
435 jump->flags |= PATCH_ABS48;
436 if (jump->flags & IS_COND) {
437 inst[0] -= 2;
438 inst++;
440 inst[4] = inst[6];
441 inst[5] = inst[7];
442 return inst + 5;
444 #endif
446 return code_ptr;
449 #ifdef __GNUC__
450 static __attribute__ ((noinline)) void sljit_cache_flush(void* code, void* code_ptr)
452 SLJIT_CACHE_FLUSH(code, code_ptr);
454 #endif
456 #if (defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64)
458 static SLJIT_INLINE sljit_sw put_label_get_length(struct sljit_put_label *put_label, sljit_uw max_label)
460 if (max_label < 0x80000000l) {
461 put_label->flags = 0;
462 return 1;
465 if (max_label < 0x800000000000l) {
466 put_label->flags = 1;
467 return 3;
470 put_label->flags = 2;
471 return 5;
474 static SLJIT_INLINE void put_label_set(struct sljit_put_label *put_label)
476 sljit_uw addr = put_label->label->addr;
477 sljit_ins *inst = (sljit_ins *)put_label->addr;
478 sljit_s32 reg = *inst;
480 if (put_label->flags == 0) {
481 SLJIT_ASSERT(addr < 0x80000000l);
482 inst[0] = LUI | T(reg) | IMM(addr >> 16);
484 else if (put_label->flags == 1) {
485 SLJIT_ASSERT(addr < 0x800000000000l);
486 inst[0] = LUI | T(reg) | IMM(addr >> 32);
487 inst[1] = ORI | S(reg) | T(reg) | IMM((addr >> 16) & 0xffff);
488 inst[2] = DSLL | T(reg) | D(reg) | SH_IMM(16);
489 inst += 2;
491 else {
492 inst[0] = LUI | T(reg) | IMM(addr >> 48);
493 inst[1] = ORI | S(reg) | T(reg) | IMM((addr >> 32) & 0xffff);
494 inst[2] = DSLL | T(reg) | D(reg) | SH_IMM(16);
495 inst[3] = ORI | S(reg) | T(reg) | IMM((addr >> 16) & 0xffff);
496 inst[4] = DSLL | T(reg) | D(reg) | SH_IMM(16);
497 inst += 4;
500 inst[1] = ORI | S(reg) | T(reg) | IMM(addr & 0xffff);
503 #endif
505 SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compiler)
507 struct sljit_memory_fragment *buf;
508 sljit_ins *code;
509 sljit_ins *code_ptr;
510 sljit_ins *buf_ptr;
511 sljit_ins *buf_end;
512 sljit_uw word_count;
513 sljit_uw next_addr;
514 sljit_sw executable_offset;
515 sljit_uw addr;
517 struct sljit_label *label;
518 struct sljit_jump *jump;
519 struct sljit_const *const_;
520 struct sljit_put_label *put_label;
522 CHECK_ERROR_PTR();
523 CHECK_PTR(check_sljit_generate_code(compiler));
524 reverse_buf(compiler);
526 code = (sljit_ins*)SLJIT_MALLOC_EXEC(compiler->size * sizeof(sljit_ins), compiler->exec_allocator_data);
527 PTR_FAIL_WITH_EXEC_IF(code);
528 buf = compiler->buf;
530 code_ptr = code;
531 word_count = 0;
532 next_addr = 0;
533 executable_offset = SLJIT_EXEC_OFFSET(code);
535 label = compiler->labels;
536 jump = compiler->jumps;
537 const_ = compiler->consts;
538 put_label = compiler->put_labels;
540 do {
541 buf_ptr = (sljit_ins*)buf->memory;
542 buf_end = buf_ptr + (buf->used_size >> 2);
543 do {
544 *code_ptr = *buf_ptr++;
545 if (next_addr == word_count) {
546 SLJIT_ASSERT(!label || label->size >= word_count);
547 SLJIT_ASSERT(!jump || jump->addr >= word_count);
548 SLJIT_ASSERT(!const_ || const_->addr >= word_count);
549 SLJIT_ASSERT(!put_label || put_label->addr >= word_count);
551 /* These structures are ordered by their address. */
552 if (label && label->size == word_count) {
553 label->addr = (sljit_uw)SLJIT_ADD_EXEC_OFFSET(code_ptr, executable_offset);
554 label->size = code_ptr - code;
555 label = label->next;
557 if (jump && jump->addr == word_count) {
558 #if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)
559 jump->addr = (sljit_uw)(code_ptr - 3);
560 #else
561 jump->addr = (sljit_uw)(code_ptr - 7);
562 #endif
563 code_ptr = detect_jump_type(jump, code_ptr, code, executable_offset);
564 jump = jump->next;
566 if (const_ && const_->addr == word_count) {
567 const_->addr = (sljit_uw)code_ptr;
568 const_ = const_->next;
570 if (put_label && put_label->addr == word_count) {
571 SLJIT_ASSERT(put_label->label);
572 put_label->addr = (sljit_uw)code_ptr;
573 #if (defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64)
574 code_ptr += put_label_get_length(put_label, (sljit_uw)(SLJIT_ADD_EXEC_OFFSET(code, executable_offset) + put_label->label->size));
575 word_count += 5;
576 #endif
577 put_label = put_label->next;
579 next_addr = compute_next_addr(label, jump, const_, put_label);
581 code_ptr ++;
582 word_count ++;
583 } while (buf_ptr < buf_end);
585 buf = buf->next;
586 } while (buf);
588 if (label && label->size == word_count) {
589 label->addr = (sljit_uw)code_ptr;
590 label->size = code_ptr - code;
591 label = label->next;
594 SLJIT_ASSERT(!label);
595 SLJIT_ASSERT(!jump);
596 SLJIT_ASSERT(!const_);
597 SLJIT_ASSERT(!put_label);
598 SLJIT_ASSERT(code_ptr - code <= (sljit_sw)compiler->size);
600 jump = compiler->jumps;
601 while (jump) {
602 do {
603 addr = (jump->flags & JUMP_LABEL) ? jump->u.label->addr : jump->u.target;
604 buf_ptr = (sljit_ins *)jump->addr;
606 if (jump->flags & PATCH_B) {
607 addr = (sljit_sw)(addr - ((sljit_uw)SLJIT_ADD_EXEC_OFFSET(buf_ptr, executable_offset) + sizeof(sljit_ins))) >> 2;
608 SLJIT_ASSERT((sljit_sw)addr <= SIMM_MAX && (sljit_sw)addr >= SIMM_MIN);
609 buf_ptr[0] = (buf_ptr[0] & 0xffff0000) | (addr & 0xffff);
610 break;
612 if (jump->flags & PATCH_J) {
613 SLJIT_ASSERT((addr & ~0xfffffff) == (((sljit_uw)SLJIT_ADD_EXEC_OFFSET(buf_ptr, executable_offset) + sizeof(sljit_ins)) & ~0xfffffff));
614 buf_ptr[0] |= (addr >> 2) & 0x03ffffff;
615 break;
618 /* Set the fields of immediate loads. */
619 #if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)
620 buf_ptr[0] = (buf_ptr[0] & 0xffff0000) | ((addr >> 16) & 0xffff);
621 buf_ptr[1] = (buf_ptr[1] & 0xffff0000) | (addr & 0xffff);
622 #else
623 if (jump->flags & PATCH_ABS32) {
624 SLJIT_ASSERT(addr <= 0x7fffffff);
625 buf_ptr[0] = (buf_ptr[0] & 0xffff0000) | ((addr >> 16) & 0xffff);
626 buf_ptr[1] = (buf_ptr[1] & 0xffff0000) | (addr & 0xffff);
628 else if (jump->flags & PATCH_ABS48) {
629 SLJIT_ASSERT(addr <= 0x7fffffffffffl);
630 buf_ptr[0] = (buf_ptr[0] & 0xffff0000) | ((addr >> 32) & 0xffff);
631 buf_ptr[1] = (buf_ptr[1] & 0xffff0000) | ((addr >> 16) & 0xffff);
632 buf_ptr[3] = (buf_ptr[3] & 0xffff0000) | (addr & 0xffff);
634 else {
635 buf_ptr[0] = (buf_ptr[0] & 0xffff0000) | ((addr >> 48) & 0xffff);
636 buf_ptr[1] = (buf_ptr[1] & 0xffff0000) | ((addr >> 32) & 0xffff);
637 buf_ptr[3] = (buf_ptr[3] & 0xffff0000) | ((addr >> 16) & 0xffff);
638 buf_ptr[5] = (buf_ptr[5] & 0xffff0000) | (addr & 0xffff);
640 #endif
641 } while (0);
642 jump = jump->next;
645 put_label = compiler->put_labels;
646 while (put_label) {
647 #if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)
648 addr = put_label->label->addr;
649 buf_ptr = (sljit_ins *)put_label->addr;
651 SLJIT_ASSERT((buf_ptr[0] & 0xffe00000) == LUI && (buf_ptr[1] & 0xfc000000) == ORI);
652 buf_ptr[0] |= (addr >> 16) & 0xffff;
653 buf_ptr[1] |= addr & 0xffff;
654 #else
655 put_label_set(put_label);
656 #endif
657 put_label = put_label->next;
660 compiler->error = SLJIT_ERR_COMPILED;
661 compiler->executable_offset = executable_offset;
662 compiler->executable_size = (code_ptr - code) * sizeof(sljit_ins);
664 code = (sljit_ins *)SLJIT_ADD_EXEC_OFFSET(code, executable_offset);
665 code_ptr = (sljit_ins *)SLJIT_ADD_EXEC_OFFSET(code_ptr, executable_offset);
667 #ifndef __GNUC__
668 SLJIT_CACHE_FLUSH(code, code_ptr);
669 #else
670 /* GCC workaround for invalid code generation with -O2. */
671 sljit_cache_flush(code, code_ptr);
672 #endif
673 SLJIT_UPDATE_WX_FLAGS(code, code_ptr, 1);
674 return code;
677 SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_has_cpu_feature(sljit_s32 feature_type)
679 sljit_sw fir = 0;
681 switch (feature_type) {
682 case SLJIT_HAS_FPU:
683 #ifdef SLJIT_IS_FPU_AVAILABLE
684 return SLJIT_IS_FPU_AVAILABLE;
685 #elif defined(__GNUC__)
686 __asm__ ("cfc1 %0, $0" : "=r"(fir));
687 return (fir >> 22) & 0x1;
688 #else
689 #error "FIR check is not implemented for this architecture"
690 #endif
691 case SLJIT_HAS_ZERO_REGISTER:
692 return 1;
694 #if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 1)
695 case SLJIT_HAS_CLZ:
696 case SLJIT_HAS_CMOV:
697 case SLJIT_HAS_PREFETCH:
698 return 1;
699 #endif /* SLJIT_MIPS_REV >= 1 */
701 default:
702 return fir;
706 /* --------------------------------------------------------------------- */
707 /* Entry, exit */
708 /* --------------------------------------------------------------------- */
710 /* Creates an index in data_transfer_insts array. */
711 #define LOAD_DATA 0x01
712 #define WORD_DATA 0x00
713 #define BYTE_DATA 0x02
714 #define HALF_DATA 0x04
715 #define INT_DATA 0x06
716 #define SIGNED_DATA 0x08
717 /* Separates integer and floating point registers */
718 #define GPR_REG 0x0f
719 #define DOUBLE_DATA 0x10
720 #define SINGLE_DATA 0x12
722 #define MEM_MASK 0x1f
724 #define ARG_TEST 0x00020
725 #define ALT_KEEP_CACHE 0x00040
726 #define CUMULATIVE_OP 0x00080
727 #define LOGICAL_OP 0x00100
728 #define IMM_OP 0x00200
729 #define MOVE_OP 0x00400
730 #define SRC2_IMM 0x00800
732 #define UNUSED_DEST 0x01000
733 #define REG_DEST 0x02000
734 #define REG1_SOURCE 0x04000
735 #define REG2_SOURCE 0x08000
736 #define SLOW_SRC1 0x10000
737 #define SLOW_SRC2 0x20000
738 #define SLOW_DEST 0x40000
740 #if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)
741 #define STACK_STORE SW
742 #define STACK_LOAD LW
743 #else
744 #define STACK_STORE SD
745 #define STACK_LOAD LD
746 #endif
748 static SLJIT_INLINE sljit_s32 emit_op_mem(struct sljit_compiler *compiler, sljit_s32 flags, sljit_s32 reg_ar, sljit_s32 arg, sljit_sw argw);
750 #if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)
751 #include "sljitNativeMIPS_32.c"
752 #else
753 #include "sljitNativeMIPS_64.c"
754 #endif
756 SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_enter(struct sljit_compiler *compiler,
757 sljit_s32 options, sljit_s32 arg_types, sljit_s32 scratches, sljit_s32 saveds,
758 sljit_s32 fscratches, sljit_s32 fsaveds, sljit_s32 local_size)
760 sljit_ins base;
761 sljit_s32 i, tmp, offs;
762 sljit_s32 arg_count, word_arg_count, float_arg_count;
764 CHECK_ERROR();
765 CHECK(check_sljit_emit_enter(compiler, options, arg_types, scratches, saveds, fscratches, fsaveds, local_size));
766 set_emit_enter(compiler, options, arg_types, scratches, saveds, fscratches, fsaveds, local_size);
768 local_size += GET_SAVED_REGISTERS_SIZE(scratches, saveds, 1) + SLJIT_LOCALS_OFFSET;
769 #if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)
770 local_size = (local_size + 15) & ~0xf;
771 #else
772 local_size = (local_size + 31) & ~0x1f;
773 #endif
774 compiler->local_size = local_size;
776 if (local_size <= -SIMM_MIN) {
777 /* Frequent case. */
778 FAIL_IF(push_inst(compiler, ADDIU_W | S(SLJIT_SP) | T(SLJIT_SP) | IMM(-local_size), DR(SLJIT_SP)));
779 base = S(SLJIT_SP);
780 offs = local_size - (sljit_sw)sizeof(sljit_sw);
782 else {
783 FAIL_IF(load_immediate(compiler, DR(OTHER_FLAG), local_size));
784 FAIL_IF(push_inst(compiler, ADDU_W | S(SLJIT_SP) | TA(0) | D(TMP_REG2), DR(TMP_REG2)));
785 FAIL_IF(push_inst(compiler, SUBU_W | S(SLJIT_SP) | T(OTHER_FLAG) | D(SLJIT_SP), DR(SLJIT_SP)));
786 base = S(TMP_REG2);
787 local_size = 0;
788 offs = -(sljit_sw)sizeof(sljit_sw);
791 FAIL_IF(push_inst(compiler, STACK_STORE | base | TA(RETURN_ADDR_REG) | IMM(offs), MOVABLE_INS));
793 tmp = saveds < SLJIT_NUMBER_OF_SAVED_REGISTERS ? (SLJIT_S0 + 1 - saveds) : SLJIT_FIRST_SAVED_REG;
794 for (i = SLJIT_S0; i >= tmp; i--) {
795 offs -= (sljit_s32)(sizeof(sljit_sw));
796 FAIL_IF(push_inst(compiler, STACK_STORE | base | T(i) | IMM(offs), MOVABLE_INS));
799 for (i = scratches; i >= SLJIT_FIRST_SAVED_REG; i--) {
800 offs -= (sljit_s32)(sizeof(sljit_sw));
801 FAIL_IF(push_inst(compiler, STACK_STORE | base | T(i) | IMM(offs), MOVABLE_INS));
804 arg_types >>= SLJIT_ARG_SHIFT;
805 arg_count = 0;
806 word_arg_count = 0;
807 float_arg_count = 0;
809 #if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)
810 /* The first maximum two floating point arguments are passed in floating point
811 registers if no integer argument precedes them. The first 16 byte data is
812 passed in four integer registers, the rest is placed onto the stack.
813 The floating point registers are also part of the first 16 byte data, so
814 their corresponding integer registers are not used when they are present. */
816 while (arg_types) {
817 switch (arg_types & SLJIT_ARG_MASK) {
818 case SLJIT_ARG_TYPE_F64:
819 float_arg_count++;
820 if ((arg_count & 0x1) != 0)
821 arg_count++;
823 if (word_arg_count == 0 && float_arg_count <= 2) {
824 if (float_arg_count == 1)
825 FAIL_IF(push_inst(compiler, MOV_S | FMT_D | FS(TMP_FREG1) | FD(SLJIT_FR0), MOVABLE_INS));
826 } else if (arg_count < 4) {
827 FAIL_IF(push_inst(compiler, MTC1 | TA(4 + arg_count) | FS(float_arg_count), MOVABLE_INS));
828 FAIL_IF(push_inst(compiler, MTC1 | TA(5 + arg_count) | FS(float_arg_count) | (1 << 11), MOVABLE_INS));
829 } else
830 FAIL_IF(push_inst(compiler, LDC1 | base | FT(float_arg_count) | IMM(local_size + (arg_count << 2)), MOVABLE_INS));
831 arg_count++;
832 break;
833 case SLJIT_ARG_TYPE_F32:
834 float_arg_count++;
836 if (word_arg_count == 0 && float_arg_count <= 2) {
837 if (float_arg_count == 1)
838 FAIL_IF(push_inst(compiler, MOV_S | FMT_S | FS(TMP_FREG1) | FD(SLJIT_FR0), MOVABLE_INS));
839 } else if (arg_count < 4)
840 FAIL_IF(push_inst(compiler, MTC1 | TA(4 + arg_count) | FS(float_arg_count), MOVABLE_INS));
841 else
842 FAIL_IF(push_inst(compiler, LWC1 | base | FT(float_arg_count) | IMM(local_size + (arg_count << 2)), MOVABLE_INS));
843 break;
844 default:
845 if (arg_count < 4)
846 FAIL_IF(push_inst(compiler, ADDU_W | SA(4 + arg_count) | TA(0) | D(SLJIT_S0 - word_arg_count),
847 DR(SLJIT_S0 - word_arg_count)));
848 else
849 FAIL_IF(push_inst(compiler, LW | base | T(SLJIT_S0 - word_arg_count) | IMM(local_size + (arg_count << 2)),
850 DR(SLJIT_S0 - word_arg_count)));
851 word_arg_count++;
852 break;
854 arg_count++;
855 arg_types >>= SLJIT_ARG_SHIFT;
857 #else /* !SLJIT_CONFIG_MIPS_32 */
858 while (arg_types) {
859 arg_count++;
860 switch (arg_types & SLJIT_ARG_MASK) {
861 case SLJIT_ARG_TYPE_F64:
862 float_arg_count++;
863 if (arg_count != float_arg_count)
864 FAIL_IF(push_inst(compiler, MOV_S | FMT_D | FS(arg_count) | FD(float_arg_count), MOVABLE_INS));
865 else if (arg_count == 1)
866 FAIL_IF(push_inst(compiler, MOV_S | FMT_D | FS(TMP_FREG1) | FD(SLJIT_FR0), MOVABLE_INS));
867 break;
868 case SLJIT_ARG_TYPE_F32:
869 float_arg_count++;
870 if (arg_count != float_arg_count)
871 FAIL_IF(push_inst(compiler, MOV_S | FMT_S | FS(arg_count) | FD(float_arg_count), MOVABLE_INS));
872 else if (arg_count == 1)
873 FAIL_IF(push_inst(compiler, MOV_S | FMT_S | FS(TMP_FREG1) | FD(SLJIT_FR0), MOVABLE_INS));
874 break;
875 default:
876 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)));
877 word_arg_count++;
878 break;
880 arg_types >>= SLJIT_ARG_SHIFT;
882 #endif /* SLJIT_CONFIG_MIPS_32 */
884 return SLJIT_SUCCESS;
887 SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_set_context(struct sljit_compiler *compiler,
888 sljit_s32 options, sljit_s32 arg_types, sljit_s32 scratches, sljit_s32 saveds,
889 sljit_s32 fscratches, sljit_s32 fsaveds, sljit_s32 local_size)
891 CHECK_ERROR();
892 CHECK(check_sljit_set_context(compiler, options, arg_types, scratches, saveds, fscratches, fsaveds, local_size));
893 set_set_context(compiler, options, arg_types, scratches, saveds, fscratches, fsaveds, local_size);
895 local_size += GET_SAVED_REGISTERS_SIZE(scratches, saveds, 1) + SLJIT_LOCALS_OFFSET;
896 #if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)
897 compiler->local_size = (local_size + 15) & ~0xf;
898 #else
899 compiler->local_size = (local_size + 31) & ~0x1f;
900 #endif
901 return SLJIT_SUCCESS;
904 SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_return_void(struct sljit_compiler *compiler)
906 sljit_s32 local_size, i, tmp, offs;
907 sljit_ins base;
909 CHECK_ERROR();
910 CHECK(check_sljit_emit_return_void(compiler));
912 local_size = compiler->local_size;
913 if (local_size <= SIMM_MAX)
914 base = S(SLJIT_SP);
915 else {
916 FAIL_IF(load_immediate(compiler, DR(TMP_REG1), local_size));
917 FAIL_IF(push_inst(compiler, ADDU_W | S(SLJIT_SP) | T(TMP_REG1) | D(TMP_REG1), DR(TMP_REG1)));
918 base = S(TMP_REG1);
919 local_size = 0;
922 FAIL_IF(push_inst(compiler, STACK_LOAD | base | TA(RETURN_ADDR_REG) | IMM(local_size - (sljit_s32)sizeof(sljit_sw)), RETURN_ADDR_REG));
923 offs = local_size - (sljit_s32)GET_SAVED_REGISTERS_SIZE(compiler->scratches, compiler->saveds, 1);
925 tmp = compiler->scratches;
926 for (i = SLJIT_FIRST_SAVED_REG; i <= tmp; i++) {
927 FAIL_IF(push_inst(compiler, STACK_LOAD | base | T(i) | IMM(offs), DR(i)));
928 offs += (sljit_s32)(sizeof(sljit_sw));
931 tmp = compiler->saveds < SLJIT_NUMBER_OF_SAVED_REGISTERS ? (SLJIT_S0 + 1 - compiler->saveds) : SLJIT_FIRST_SAVED_REG;
932 for (i = tmp; i <= SLJIT_S0; i++) {
933 FAIL_IF(push_inst(compiler, STACK_LOAD | base | T(i) | IMM(offs), DR(i)));
934 offs += (sljit_s32)(sizeof(sljit_sw));
937 SLJIT_ASSERT(offs == local_size - (sljit_sw)(sizeof(sljit_sw)));
939 FAIL_IF(push_inst(compiler, JR | SA(RETURN_ADDR_REG), UNMOVABLE_INS));
940 if (compiler->local_size <= SIMM_MAX)
941 return push_inst(compiler, ADDIU_W | S(SLJIT_SP) | T(SLJIT_SP) | IMM(compiler->local_size), UNMOVABLE_INS);
942 else
943 return push_inst(compiler, ADDU_W | S(TMP_REG1) | TA(0) | D(SLJIT_SP), UNMOVABLE_INS);
946 #undef STACK_STORE
947 #undef STACK_LOAD
949 /* --------------------------------------------------------------------- */
950 /* Operators */
951 /* --------------------------------------------------------------------- */
953 #if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)
954 #define ARCH_32_64(a, b) a
955 #else
956 #define ARCH_32_64(a, b) b
957 #endif
959 static const sljit_ins data_transfer_insts[16 + 4] = {
960 /* u w s */ ARCH_32_64(HI(43) /* sw */, HI(63) /* sd */),
961 /* u w l */ ARCH_32_64(HI(35) /* lw */, HI(55) /* ld */),
962 /* u b s */ HI(40) /* sb */,
963 /* u b l */ HI(36) /* lbu */,
964 /* u h s */ HI(41) /* sh */,
965 /* u h l */ HI(37) /* lhu */,
966 /* u i s */ HI(43) /* sw */,
967 /* u i l */ ARCH_32_64(HI(35) /* lw */, HI(39) /* lwu */),
969 /* s w s */ ARCH_32_64(HI(43) /* sw */, HI(63) /* sd */),
970 /* s w l */ ARCH_32_64(HI(35) /* lw */, HI(55) /* ld */),
971 /* s b s */ HI(40) /* sb */,
972 /* s b l */ HI(32) /* lb */,
973 /* s h s */ HI(41) /* sh */,
974 /* s h l */ HI(33) /* lh */,
975 /* s i s */ HI(43) /* sw */,
976 /* s i l */ HI(35) /* lw */,
978 /* d s */ HI(61) /* sdc1 */,
979 /* d l */ HI(53) /* ldc1 */,
980 /* s s */ HI(57) /* swc1 */,
981 /* s l */ HI(49) /* lwc1 */,
984 #undef ARCH_32_64
986 /* reg_ar is an absoulute register! */
988 /* Can perform an operation using at most 1 instruction. */
989 static sljit_s32 getput_arg_fast(struct sljit_compiler *compiler, sljit_s32 flags, sljit_s32 reg_ar, sljit_s32 arg, sljit_sw argw)
991 SLJIT_ASSERT(arg & SLJIT_MEM);
993 if (!(arg & OFFS_REG_MASK) && argw <= SIMM_MAX && argw >= SIMM_MIN) {
994 /* Works for both absoulte and relative addresses. */
995 if (SLJIT_UNLIKELY(flags & ARG_TEST))
996 return 1;
997 FAIL_IF(push_inst(compiler, data_transfer_insts[flags & MEM_MASK] | S(arg & REG_MASK)
998 | TA(reg_ar) | IMM(argw), ((flags & MEM_MASK) <= GPR_REG && (flags & LOAD_DATA)) ? reg_ar : MOVABLE_INS));
999 return -1;
1001 return 0;
1004 /* See getput_arg below.
1005 Note: can_cache is called only for binary operators. Those
1006 operators always uses word arguments without write back. */
1007 static sljit_s32 can_cache(sljit_s32 arg, sljit_sw argw, sljit_s32 next_arg, sljit_sw next_argw)
1009 SLJIT_ASSERT((arg & SLJIT_MEM) && (next_arg & SLJIT_MEM));
1011 /* Simple operation except for updates. */
1012 if (arg & OFFS_REG_MASK) {
1013 argw &= 0x3;
1014 next_argw &= 0x3;
1015 if (argw && argw == next_argw && (arg == next_arg || (arg & OFFS_REG_MASK) == (next_arg & OFFS_REG_MASK)))
1016 return 1;
1017 return 0;
1020 if (arg == next_arg) {
1021 if (((next_argw - argw) <= SIMM_MAX && (next_argw - argw) >= SIMM_MIN))
1022 return 1;
1023 return 0;
1026 return 0;
1029 /* Emit the necessary instructions. See can_cache above. */
1030 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)
1032 sljit_s32 tmp_ar, base, delay_slot;
1034 SLJIT_ASSERT(arg & SLJIT_MEM);
1035 if (!(next_arg & SLJIT_MEM)) {
1036 next_arg = 0;
1037 next_argw = 0;
1040 if ((flags & MEM_MASK) <= GPR_REG && (flags & LOAD_DATA)) {
1041 tmp_ar = reg_ar;
1042 delay_slot = reg_ar;
1044 else {
1045 tmp_ar = DR(TMP_REG1);
1046 delay_slot = MOVABLE_INS;
1048 base = arg & REG_MASK;
1050 if (SLJIT_UNLIKELY(arg & OFFS_REG_MASK)) {
1051 argw &= 0x3;
1053 /* Using the cache. */
1054 if (argw == compiler->cache_argw) {
1055 if (arg == compiler->cache_arg)
1056 return push_inst(compiler, data_transfer_insts[flags & MEM_MASK] | S(TMP_REG3) | TA(reg_ar), delay_slot);
1058 if ((SLJIT_MEM | (arg & OFFS_REG_MASK)) == compiler->cache_arg) {
1059 if (arg == next_arg && argw == (next_argw & 0x3)) {
1060 compiler->cache_arg = arg;
1061 compiler->cache_argw = argw;
1062 FAIL_IF(push_inst(compiler, ADDU_W | S(base) | T(TMP_REG3) | D(TMP_REG3), DR(TMP_REG3)));
1063 return push_inst(compiler, data_transfer_insts[flags & MEM_MASK] | S(TMP_REG3) | TA(reg_ar), delay_slot);
1065 FAIL_IF(push_inst(compiler, ADDU_W | S(base) | T(TMP_REG3) | DA(tmp_ar), tmp_ar));
1066 return push_inst(compiler, data_transfer_insts[flags & MEM_MASK] | SA(tmp_ar) | TA(reg_ar), delay_slot);
1070 if (SLJIT_UNLIKELY(argw)) {
1071 compiler->cache_arg = SLJIT_MEM | (arg & OFFS_REG_MASK);
1072 compiler->cache_argw = argw;
1073 FAIL_IF(push_inst(compiler, SLL_W | T(OFFS_REG(arg)) | D(TMP_REG3) | SH_IMM(argw), DR(TMP_REG3)));
1076 if (arg == next_arg && argw == (next_argw & 0x3)) {
1077 compiler->cache_arg = arg;
1078 compiler->cache_argw = argw;
1079 FAIL_IF(push_inst(compiler, ADDU_W | S(base) | T(!argw ? OFFS_REG(arg) : TMP_REG3) | D(TMP_REG3), DR(TMP_REG3)));
1080 tmp_ar = DR(TMP_REG3);
1082 else
1083 FAIL_IF(push_inst(compiler, ADDU_W | S(base) | T(!argw ? OFFS_REG(arg) : TMP_REG3) | DA(tmp_ar), tmp_ar));
1084 return push_inst(compiler, data_transfer_insts[flags & MEM_MASK] | SA(tmp_ar) | TA(reg_ar), delay_slot);
1087 if (compiler->cache_arg == arg && argw - compiler->cache_argw <= SIMM_MAX && argw - compiler->cache_argw >= SIMM_MIN) {
1088 if (argw != compiler->cache_argw) {
1089 FAIL_IF(push_inst(compiler, ADDIU_W | S(TMP_REG3) | T(TMP_REG3) | IMM(argw - compiler->cache_argw), DR(TMP_REG3)));
1090 compiler->cache_argw = argw;
1092 return push_inst(compiler, data_transfer_insts[flags & MEM_MASK] | S(TMP_REG3) | TA(reg_ar), delay_slot);
1095 if (compiler->cache_arg == SLJIT_MEM && argw - compiler->cache_argw <= SIMM_MAX && argw - compiler->cache_argw >= SIMM_MIN) {
1096 if (argw != compiler->cache_argw)
1097 FAIL_IF(push_inst(compiler, ADDIU_W | S(TMP_REG3) | T(TMP_REG3) | IMM(argw - compiler->cache_argw), DR(TMP_REG3)));
1099 else {
1100 compiler->cache_arg = SLJIT_MEM;
1101 FAIL_IF(load_immediate(compiler, DR(TMP_REG3), argw));
1103 compiler->cache_argw = argw;
1105 if (!base)
1106 return push_inst(compiler, data_transfer_insts[flags & MEM_MASK] | S(TMP_REG3) | TA(reg_ar), delay_slot);
1108 if (arg == next_arg && next_argw - argw <= SIMM_MAX && next_argw - argw >= SIMM_MIN) {
1109 compiler->cache_arg = arg;
1110 FAIL_IF(push_inst(compiler, ADDU_W | S(TMP_REG3) | T(base) | D(TMP_REG3), DR(TMP_REG3)));
1111 return push_inst(compiler, data_transfer_insts[flags & MEM_MASK] | S(TMP_REG3) | TA(reg_ar), delay_slot);
1114 FAIL_IF(push_inst(compiler, ADDU_W | S(TMP_REG3) | T(base) | DA(tmp_ar), tmp_ar));
1115 return push_inst(compiler, data_transfer_insts[flags & MEM_MASK] | SA(tmp_ar) | TA(reg_ar), delay_slot);
1118 static SLJIT_INLINE sljit_s32 emit_op_mem(struct sljit_compiler *compiler, sljit_s32 flags, sljit_s32 reg_ar, sljit_s32 arg, sljit_sw argw)
1120 sljit_s32 tmp_ar, base, delay_slot;
1122 if (getput_arg_fast(compiler, flags, reg_ar, arg, argw))
1123 return compiler->error;
1125 if ((flags & MEM_MASK) <= GPR_REG && (flags & LOAD_DATA)) {
1126 tmp_ar = reg_ar;
1127 delay_slot = reg_ar;
1129 else {
1130 tmp_ar = DR(TMP_REG1);
1131 delay_slot = MOVABLE_INS;
1133 base = arg & REG_MASK;
1135 if (SLJIT_UNLIKELY(arg & OFFS_REG_MASK)) {
1136 argw &= 0x3;
1138 if (SLJIT_UNLIKELY(argw)) {
1139 FAIL_IF(push_inst(compiler, SLL_W | T(OFFS_REG(arg)) | DA(tmp_ar) | SH_IMM(argw), tmp_ar));
1140 FAIL_IF(push_inst(compiler, ADDU_W | S(base) | TA(tmp_ar) | DA(tmp_ar), tmp_ar));
1142 else
1143 FAIL_IF(push_inst(compiler, ADDU_W | S(base) | T(OFFS_REG(arg)) | DA(tmp_ar), tmp_ar));
1144 return push_inst(compiler, data_transfer_insts[flags & MEM_MASK] | SA(tmp_ar) | TA(reg_ar), delay_slot);
1147 FAIL_IF(load_immediate(compiler, tmp_ar, argw));
1149 if (base != 0)
1150 FAIL_IF(push_inst(compiler, ADDU_W | S(base) | TA(tmp_ar) | DA(tmp_ar), tmp_ar));
1152 return push_inst(compiler, data_transfer_insts[flags & MEM_MASK] | SA(tmp_ar) | TA(reg_ar), delay_slot);
1155 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)
1157 if (getput_arg_fast(compiler, flags, reg, arg1, arg1w))
1158 return compiler->error;
1159 return getput_arg(compiler, flags, reg, arg1, arg1w, arg2, arg2w);
1162 static sljit_s32 emit_op(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 flags,
1163 sljit_s32 dst, sljit_sw dstw,
1164 sljit_s32 src1, sljit_sw src1w,
1165 sljit_s32 src2, sljit_sw src2w)
1167 /* arg1 goes to TMP_REG1 or src reg
1168 arg2 goes to TMP_REG2, imm or src reg
1169 TMP_REG3 can be used for caching
1170 result goes to TMP_REG2, so put result can use TMP_REG1 and TMP_REG3. */
1171 sljit_s32 dst_r = TMP_REG2;
1172 sljit_s32 src1_r;
1173 sljit_sw src2_r = 0;
1174 sljit_s32 sugg_src2_r = TMP_REG2;
1176 if (!(flags & ALT_KEEP_CACHE)) {
1177 compiler->cache_arg = 0;
1178 compiler->cache_argw = 0;
1181 if (dst == TMP_REG2) {
1182 SLJIT_ASSERT(HAS_FLAGS(op));
1183 flags |= UNUSED_DEST;
1185 else if (FAST_IS_REG(dst)) {
1186 dst_r = dst;
1187 flags |= REG_DEST;
1188 if (flags & MOVE_OP)
1189 sugg_src2_r = dst_r;
1191 else if ((dst & SLJIT_MEM) && !getput_arg_fast(compiler, flags | ARG_TEST, DR(TMP_REG1), dst, dstw))
1192 flags |= SLOW_DEST;
1194 if (flags & IMM_OP) {
1195 if ((src2 & SLJIT_IMM) && src2w) {
1196 if ((!(flags & LOGICAL_OP) && (src2w <= SIMM_MAX && src2w >= SIMM_MIN))
1197 || ((flags & LOGICAL_OP) && !(src2w & ~UIMM_MAX))) {
1198 flags |= SRC2_IMM;
1199 src2_r = src2w;
1202 if (!(flags & SRC2_IMM) && (flags & CUMULATIVE_OP) && (src1 & SLJIT_IMM) && src1w) {
1203 if ((!(flags & LOGICAL_OP) && (src1w <= SIMM_MAX && src1w >= SIMM_MIN))
1204 || ((flags & LOGICAL_OP) && !(src1w & ~UIMM_MAX))) {
1205 flags |= SRC2_IMM;
1206 src2_r = src1w;
1208 /* And swap arguments. */
1209 src1 = src2;
1210 src1w = src2w;
1211 src2 = SLJIT_IMM;
1212 /* src2w = src2_r unneeded. */
1217 /* Source 1. */
1218 if (FAST_IS_REG(src1)) {
1219 src1_r = src1;
1220 flags |= REG1_SOURCE;
1222 else if (src1 & SLJIT_IMM) {
1223 if (src1w) {
1224 FAIL_IF(load_immediate(compiler, DR(TMP_REG1), src1w));
1225 src1_r = TMP_REG1;
1227 else
1228 src1_r = 0;
1230 else {
1231 if (getput_arg_fast(compiler, flags | LOAD_DATA, DR(TMP_REG1), src1, src1w))
1232 FAIL_IF(compiler->error);
1233 else
1234 flags |= SLOW_SRC1;
1235 src1_r = TMP_REG1;
1238 /* Source 2. */
1239 if (FAST_IS_REG(src2)) {
1240 src2_r = src2;
1241 flags |= REG2_SOURCE;
1242 if ((flags & (REG_DEST | MOVE_OP)) == MOVE_OP)
1243 dst_r = src2_r;
1245 else if (src2 & SLJIT_IMM) {
1246 if (!(flags & SRC2_IMM)) {
1247 if (src2w) {
1248 FAIL_IF(load_immediate(compiler, DR(sugg_src2_r), src2w));
1249 src2_r = sugg_src2_r;
1251 else {
1252 src2_r = 0;
1253 if (flags & MOVE_OP) {
1254 if (dst & SLJIT_MEM)
1255 dst_r = 0;
1256 else
1257 op = SLJIT_MOV;
1262 else {
1263 if (getput_arg_fast(compiler, flags | LOAD_DATA, DR(sugg_src2_r), src2, src2w))
1264 FAIL_IF(compiler->error);
1265 else
1266 flags |= SLOW_SRC2;
1267 src2_r = sugg_src2_r;
1270 if ((flags & (SLOW_SRC1 | SLOW_SRC2)) == (SLOW_SRC1 | SLOW_SRC2)) {
1271 SLJIT_ASSERT(src2_r == TMP_REG2);
1272 if (!can_cache(src1, src1w, src2, src2w) && can_cache(src1, src1w, dst, dstw)) {
1273 FAIL_IF(getput_arg(compiler, flags | LOAD_DATA, DR(TMP_REG2), src2, src2w, src1, src1w));
1274 FAIL_IF(getput_arg(compiler, flags | LOAD_DATA, DR(TMP_REG1), src1, src1w, dst, dstw));
1276 else {
1277 FAIL_IF(getput_arg(compiler, flags | LOAD_DATA, DR(TMP_REG1), src1, src1w, src2, src2w));
1278 FAIL_IF(getput_arg(compiler, flags | LOAD_DATA, DR(TMP_REG2), src2, src2w, dst, dstw));
1281 else if (flags & SLOW_SRC1)
1282 FAIL_IF(getput_arg(compiler, flags | LOAD_DATA, DR(TMP_REG1), src1, src1w, dst, dstw));
1283 else if (flags & SLOW_SRC2)
1284 FAIL_IF(getput_arg(compiler, flags | LOAD_DATA, DR(sugg_src2_r), src2, src2w, dst, dstw));
1286 FAIL_IF(emit_single_op(compiler, op, flags, dst_r, src1_r, src2_r));
1288 if (dst & SLJIT_MEM) {
1289 if (!(flags & SLOW_DEST)) {
1290 getput_arg_fast(compiler, flags, DR(dst_r), dst, dstw);
1291 return compiler->error;
1293 return getput_arg(compiler, flags, DR(dst_r), dst, dstw, 0, 0);
1296 return SLJIT_SUCCESS;
1299 SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op0(struct sljit_compiler *compiler, sljit_s32 op)
1301 #if (defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64)
1302 sljit_s32 int_op = op & SLJIT_32;
1303 #endif
1305 CHECK_ERROR();
1306 CHECK(check_sljit_emit_op0(compiler, op));
1308 op = GET_OPCODE(op);
1309 switch (op) {
1310 case SLJIT_BREAKPOINT:
1311 return push_inst(compiler, BREAK, UNMOVABLE_INS);
1312 case SLJIT_NOP:
1313 return push_inst(compiler, NOP, UNMOVABLE_INS);
1314 case SLJIT_LMUL_UW:
1315 case SLJIT_LMUL_SW:
1316 #if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 6)
1317 #if (defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64)
1318 FAIL_IF(push_inst(compiler, (op == SLJIT_LMUL_UW ? DMULU : DMUL) | S(SLJIT_R0) | T(SLJIT_R1) | D(TMP_REG3), DR(TMP_REG3)));
1319 FAIL_IF(push_inst(compiler, (op == SLJIT_LMUL_UW ? DMUHU : DMUH) | S(SLJIT_R0) | T(SLJIT_R1) | D(TMP_REG1), DR(TMP_REG1)));
1320 #else /* !SLJIT_CONFIG_MIPS_64 */
1321 FAIL_IF(push_inst(compiler, (op == SLJIT_LMUL_UW ? MULU : MUL) | S(SLJIT_R0) | T(SLJIT_R1) | D(TMP_REG3), DR(TMP_REG3)));
1322 FAIL_IF(push_inst(compiler, (op == SLJIT_LMUL_UW ? MUHU : MUH) | S(SLJIT_R0) | T(SLJIT_R1) | D(TMP_REG1), DR(TMP_REG1)));
1323 #endif /* SLJIT_CONFIG_MIPS_64 */
1324 FAIL_IF(push_inst(compiler, ADDU_W | S(TMP_REG3) | TA(0) | D(SLJIT_R0), DR(SLJIT_R0)));
1325 return push_inst(compiler, ADDU_W | S(TMP_REG1) | TA(0) | D(SLJIT_R1), DR(SLJIT_R1));
1326 #else /* SLJIT_MIPS_REV < 6 */
1327 #if (defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64)
1328 FAIL_IF(push_inst(compiler, (op == SLJIT_LMUL_UW ? DMULTU : DMULT) | S(SLJIT_R0) | T(SLJIT_R1), MOVABLE_INS));
1329 #else /* !SLJIT_CONFIG_MIPS_64 */
1330 FAIL_IF(push_inst(compiler, (op == SLJIT_LMUL_UW ? MULTU : MULT) | S(SLJIT_R0) | T(SLJIT_R1), MOVABLE_INS));
1331 #endif /* SLJIT_CONFIG_MIPS_64 */
1332 FAIL_IF(push_inst(compiler, MFLO | D(SLJIT_R0), DR(SLJIT_R0)));
1333 return push_inst(compiler, MFHI | D(SLJIT_R1), DR(SLJIT_R1));
1334 #endif /* SLJIT_MIPS_REV >= 6 */
1335 case SLJIT_DIVMOD_UW:
1336 case SLJIT_DIVMOD_SW:
1337 case SLJIT_DIV_UW:
1338 case SLJIT_DIV_SW:
1339 SLJIT_COMPILE_ASSERT((SLJIT_DIVMOD_UW & 0x2) == 0 && SLJIT_DIV_UW - 0x2 == SLJIT_DIVMOD_UW, bad_div_opcode_assignments);
1340 #if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 6)
1341 #if (defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64)
1342 if (int_op) {
1343 FAIL_IF(push_inst(compiler, ((op | 0x2) == SLJIT_DIV_UW ? DIVU : DIV) | S(SLJIT_R0) | T(SLJIT_R1) | D(TMP_REG3), DR(TMP_REG3)));
1344 FAIL_IF(push_inst(compiler, ((op | 0x2) == SLJIT_DIV_UW ? MODU : MOD) | S(SLJIT_R0) | T(SLJIT_R1) | D(TMP_REG1), DR(TMP_REG1)));
1346 else {
1347 FAIL_IF(push_inst(compiler, ((op | 0x2) == SLJIT_DIV_UW ? DDIVU : DDIV) | S(SLJIT_R0) | T(SLJIT_R1) | D(TMP_REG3), DR(TMP_REG3)));
1348 FAIL_IF(push_inst(compiler, ((op | 0x2) == SLJIT_DIV_UW ? DMODU : DMOD) | S(SLJIT_R0) | T(SLJIT_R1) | D(TMP_REG1), DR(TMP_REG1)));
1350 #else /* !SLJIT_CONFIG_MIPS_64 */
1351 FAIL_IF(push_inst(compiler, ((op | 0x2) == SLJIT_DIV_UW ? DIVU : DIV) | S(SLJIT_R0) | T(SLJIT_R1) | D(TMP_REG3), DR(TMP_REG3)));
1352 FAIL_IF(push_inst(compiler, ((op | 0x2) == SLJIT_DIV_UW ? MODU : MOD) | S(SLJIT_R0) | T(SLJIT_R1) | D(TMP_REG1), DR(TMP_REG1)));
1353 #endif /* SLJIT_CONFIG_MIPS_64 */
1354 FAIL_IF(push_inst(compiler, ADDU_W | S(TMP_REG3) | TA(0) | D(SLJIT_R0), DR(SLJIT_R0)));
1355 return (op >= SLJIT_DIV_UW) ? SLJIT_SUCCESS : push_inst(compiler, ADDU_W | S(TMP_REG1) | TA(0) | D(SLJIT_R1), DR(SLJIT_R1));
1356 #else /* SLJIT_MIPS_REV < 6 */
1357 #if !(defined SLJIT_MIPS_REV)
1358 FAIL_IF(push_inst(compiler, NOP, UNMOVABLE_INS));
1359 FAIL_IF(push_inst(compiler, NOP, UNMOVABLE_INS));
1360 #endif /* !SLJIT_MIPS_REV */
1361 #if (defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64)
1362 if (int_op)
1363 FAIL_IF(push_inst(compiler, ((op | 0x2) == SLJIT_DIV_UW ? DIVU : DIV) | S(SLJIT_R0) | T(SLJIT_R1), MOVABLE_INS));
1364 else
1365 FAIL_IF(push_inst(compiler, ((op | 0x2) == SLJIT_DIV_UW ? DDIVU : DDIV) | S(SLJIT_R0) | T(SLJIT_R1), MOVABLE_INS));
1366 #else /* !SLJIT_CONFIG_MIPS_64 */
1367 FAIL_IF(push_inst(compiler, ((op | 0x2) == SLJIT_DIV_UW ? DIVU : DIV) | S(SLJIT_R0) | T(SLJIT_R1), MOVABLE_INS));
1368 #endif /* SLJIT_CONFIG_MIPS_64 */
1369 FAIL_IF(push_inst(compiler, MFLO | D(SLJIT_R0), DR(SLJIT_R0)));
1370 return (op >= SLJIT_DIV_UW) ? SLJIT_SUCCESS : push_inst(compiler, MFHI | D(SLJIT_R1), DR(SLJIT_R1));
1371 #endif /* SLJIT_MIPS_REV >= 6 */
1372 case SLJIT_ENDBR:
1373 case SLJIT_SKIP_FRAMES_BEFORE_RETURN:
1374 return SLJIT_SUCCESS;
1377 return SLJIT_SUCCESS;
1380 #if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 1)
1381 static sljit_s32 emit_prefetch(struct sljit_compiler *compiler,
1382 sljit_s32 src, sljit_sw srcw)
1384 if (!(src & OFFS_REG_MASK)) {
1385 if (srcw <= SIMM_MAX && srcw >= SIMM_MIN)
1386 return push_inst(compiler, PREF | S(src & REG_MASK) | IMM(srcw), MOVABLE_INS);
1388 FAIL_IF(load_immediate(compiler, DR(TMP_REG1), srcw));
1389 return push_inst(compiler, PREFX | S(src & REG_MASK) | T(TMP_REG1), MOVABLE_INS);
1392 srcw &= 0x3;
1394 if (SLJIT_UNLIKELY(srcw != 0)) {
1395 FAIL_IF(push_inst(compiler, SLL_W | T(OFFS_REG(src)) | D(TMP_REG1) | SH_IMM(srcw), DR(TMP_REG1)));
1396 return push_inst(compiler, PREFX | S(src & REG_MASK) | T(TMP_REG1), MOVABLE_INS);
1399 return push_inst(compiler, PREFX | S(src & REG_MASK) | T(OFFS_REG(src)), MOVABLE_INS);
1401 #endif /* SLJIT_MIPS_REV >= 1 */
1403 SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op1(struct sljit_compiler *compiler, sljit_s32 op,
1404 sljit_s32 dst, sljit_sw dstw,
1405 sljit_s32 src, sljit_sw srcw)
1407 sljit_s32 flags = 0;
1409 CHECK_ERROR();
1410 CHECK(check_sljit_emit_op1(compiler, op, dst, dstw, src, srcw));
1411 ADJUST_LOCAL_OFFSET(dst, dstw);
1412 ADJUST_LOCAL_OFFSET(src, srcw);
1414 #if (defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64)
1415 if (op & SLJIT_32)
1416 flags = INT_DATA | SIGNED_DATA;
1417 #endif
1419 switch (GET_OPCODE(op)) {
1420 case SLJIT_MOV:
1421 #if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)
1422 case SLJIT_MOV_U32:
1423 case SLJIT_MOV_S32:
1424 case SLJIT_MOV32:
1425 #endif
1426 case SLJIT_MOV_P:
1427 return emit_op(compiler, SLJIT_MOV, WORD_DATA | MOVE_OP, dst, dstw, TMP_REG1, 0, src, srcw);
1429 #if (defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64)
1430 case SLJIT_MOV_U32:
1431 return emit_op(compiler, SLJIT_MOV_U32, INT_DATA | MOVE_OP, dst, dstw, TMP_REG1, 0, src, (src & SLJIT_IMM) ? (sljit_u32)srcw : srcw);
1433 case SLJIT_MOV_S32:
1434 case SLJIT_MOV32:
1435 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);
1436 #endif
1438 case SLJIT_MOV_U8:
1439 return emit_op(compiler, op, BYTE_DATA | MOVE_OP, dst, dstw, TMP_REG1, 0, src, (src & SLJIT_IMM) ? (sljit_u8)srcw : srcw);
1441 case SLJIT_MOV_S8:
1442 return emit_op(compiler, op, BYTE_DATA | SIGNED_DATA | MOVE_OP, dst, dstw, TMP_REG1, 0, src, (src & SLJIT_IMM) ? (sljit_s8)srcw : srcw);
1444 case SLJIT_MOV_U16:
1445 return emit_op(compiler, op, HALF_DATA | MOVE_OP, dst, dstw, TMP_REG1, 0, src, (src & SLJIT_IMM) ? (sljit_u16)srcw : srcw);
1447 case SLJIT_MOV_S16:
1448 return emit_op(compiler, op, HALF_DATA | SIGNED_DATA | MOVE_OP, dst, dstw, TMP_REG1, 0, src, (src & SLJIT_IMM) ? (sljit_s16)srcw : srcw);
1450 case SLJIT_NOT:
1451 return emit_op(compiler, op, flags, dst, dstw, TMP_REG1, 0, src, srcw);
1453 case SLJIT_NEG:
1454 compiler->status_flags_state = SLJIT_CURRENT_FLAGS_ADD_SUB;
1455 return emit_op(compiler, SLJIT_SUB | GET_ALL_FLAGS(op), flags | IMM_OP, dst, dstw, SLJIT_IMM, 0, src, srcw);
1457 case SLJIT_CLZ:
1458 return emit_op(compiler, op, flags, dst, dstw, TMP_REG1, 0, src, srcw);
1461 SLJIT_UNREACHABLE();
1462 return SLJIT_SUCCESS;
1465 SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op2(struct sljit_compiler *compiler, sljit_s32 op,
1466 sljit_s32 dst, sljit_sw dstw,
1467 sljit_s32 src1, sljit_sw src1w,
1468 sljit_s32 src2, sljit_sw src2w)
1470 sljit_s32 flags = 0;
1472 CHECK_ERROR();
1473 CHECK(check_sljit_emit_op2(compiler, op, 0, dst, dstw, src1, src1w, src2, src2w));
1474 ADJUST_LOCAL_OFFSET(dst, dstw);
1475 ADJUST_LOCAL_OFFSET(src1, src1w);
1476 ADJUST_LOCAL_OFFSET(src2, src2w);
1478 #if (defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64)
1479 if (op & SLJIT_32) {
1480 flags |= INT_DATA | SIGNED_DATA;
1481 if (src1 & SLJIT_IMM)
1482 src1w = (sljit_s32)src1w;
1483 if (src2 & SLJIT_IMM)
1484 src2w = (sljit_s32)src2w;
1486 #endif
1488 switch (GET_OPCODE(op)) {
1489 case SLJIT_ADD:
1490 case SLJIT_ADDC:
1491 compiler->status_flags_state = SLJIT_CURRENT_FLAGS_ADD_SUB;
1492 return emit_op(compiler, op, flags | CUMULATIVE_OP | IMM_OP, dst, dstw, src1, src1w, src2, src2w);
1494 case SLJIT_SUB:
1495 case SLJIT_SUBC:
1496 compiler->status_flags_state = SLJIT_CURRENT_FLAGS_ADD_SUB;
1497 return emit_op(compiler, op, flags | IMM_OP, dst, dstw, src1, src1w, src2, src2w);
1499 case SLJIT_MUL:
1500 compiler->status_flags_state = 0;
1501 return emit_op(compiler, op, flags | CUMULATIVE_OP, dst, dstw, src1, src1w, src2, src2w);
1503 case SLJIT_AND:
1504 case SLJIT_OR:
1505 case SLJIT_XOR:
1506 return emit_op(compiler, op, flags | CUMULATIVE_OP | LOGICAL_OP | IMM_OP, dst, dstw, src1, src1w, src2, src2w);
1508 case SLJIT_SHL:
1509 case SLJIT_LSHR:
1510 case SLJIT_ASHR:
1511 #if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)
1512 if (src2 & SLJIT_IMM)
1513 src2w &= 0x1f;
1514 #else
1515 if (src2 & SLJIT_IMM) {
1516 if (op & SLJIT_32)
1517 src2w &= 0x1f;
1518 else
1519 src2w &= 0x3f;
1521 #endif
1522 return emit_op(compiler, op, flags | IMM_OP, dst, dstw, src1, src1w, src2, src2w);
1525 SLJIT_UNREACHABLE();
1526 return SLJIT_SUCCESS;
1529 SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op2u(struct sljit_compiler *compiler, sljit_s32 op,
1530 sljit_s32 src1, sljit_sw src1w,
1531 sljit_s32 src2, sljit_sw src2w)
1533 CHECK_ERROR();
1534 CHECK(check_sljit_emit_op2(compiler, op, 1, 0, 0, src1, src1w, src2, src2w));
1536 #if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) \
1537 || (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
1538 compiler->skip_checks = 1;
1539 #endif
1540 return sljit_emit_op2(compiler, op, TMP_REG2, 0, src1, src1w, src2, src2w);
1543 SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_src(struct sljit_compiler *compiler, sljit_s32 op,
1544 sljit_s32 src, sljit_sw srcw)
1546 CHECK_ERROR();
1547 CHECK(check_sljit_emit_op_src(compiler, op, src, srcw));
1548 ADJUST_LOCAL_OFFSET(src, srcw);
1550 switch (op) {
1551 case SLJIT_FAST_RETURN:
1552 if (FAST_IS_REG(src))
1553 FAIL_IF(push_inst(compiler, ADDU_W | S(src) | TA(0) | DA(RETURN_ADDR_REG), RETURN_ADDR_REG));
1554 else
1555 FAIL_IF(emit_op_mem(compiler, WORD_DATA | LOAD_DATA, RETURN_ADDR_REG, src, srcw));
1557 FAIL_IF(push_inst(compiler, JR | SA(RETURN_ADDR_REG), UNMOVABLE_INS));
1558 return push_inst(compiler, NOP, UNMOVABLE_INS);
1559 case SLJIT_SKIP_FRAMES_BEFORE_FAST_RETURN:
1560 return SLJIT_SUCCESS;
1561 case SLJIT_PREFETCH_L1:
1562 case SLJIT_PREFETCH_L2:
1563 case SLJIT_PREFETCH_L3:
1564 case SLJIT_PREFETCH_ONCE:
1565 #if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 1)
1566 return emit_prefetch(compiler, src, srcw);
1567 #else /* SLJIT_MIPS_REV < 1 */
1568 return SLJIT_SUCCESS;
1569 #endif /* SLJIT_MIPS_REV >= 1 */
1572 return SLJIT_SUCCESS;
1575 SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_get_register_index(sljit_s32 reg)
1577 CHECK_REG_INDEX(check_sljit_get_register_index(reg));
1578 return reg_map[reg];
1581 SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_get_float_register_index(sljit_s32 reg)
1583 CHECK_REG_INDEX(check_sljit_get_float_register_index(reg));
1584 return FR(reg);
1587 SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_custom(struct sljit_compiler *compiler,
1588 void *instruction, sljit_s32 size)
1590 CHECK_ERROR();
1591 CHECK(check_sljit_emit_op_custom(compiler, instruction, size));
1593 return push_inst(compiler, *(sljit_ins*)instruction, UNMOVABLE_INS);
1596 /* --------------------------------------------------------------------- */
1597 /* Floating point operators */
1598 /* --------------------------------------------------------------------- */
1600 #define FLOAT_DATA(op) (DOUBLE_DATA | ((op & SLJIT_32) >> 7))
1601 #define FMT(op) (((op & SLJIT_32) ^ SLJIT_32) << (21 - 8))
1603 static SLJIT_INLINE sljit_s32 sljit_emit_fop1_conv_sw_from_f64(struct sljit_compiler *compiler, sljit_s32 op,
1604 sljit_s32 dst, sljit_sw dstw,
1605 sljit_s32 src, sljit_sw srcw)
1607 #if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)
1608 # define flags 0
1609 #else
1610 sljit_s32 flags = (GET_OPCODE(op) == SLJIT_CONV_SW_FROM_F64) << 21;
1611 #endif
1613 if (src & SLJIT_MEM) {
1614 FAIL_IF(emit_op_mem2(compiler, FLOAT_DATA(op) | LOAD_DATA, FR(TMP_FREG1), src, srcw, dst, dstw));
1615 src = TMP_FREG1;
1618 FAIL_IF(push_inst(compiler, (TRUNC_W_S ^ (flags >> 19)) | FMT(op) | FS(src) | FD(TMP_FREG1), MOVABLE_INS));
1620 if (FAST_IS_REG(dst))
1621 return push_inst(compiler, MFC1 | flags | T(dst) | FS(TMP_FREG1), MOVABLE_INS);
1623 /* Store the integer value from a VFP register. */
1624 return emit_op_mem2(compiler, flags ? DOUBLE_DATA : SINGLE_DATA, FR(TMP_FREG1), dst, dstw, 0, 0);
1626 #if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)
1627 # undef is_long
1628 #endif
1631 static SLJIT_INLINE sljit_s32 sljit_emit_fop1_conv_f64_from_sw(struct sljit_compiler *compiler, sljit_s32 op,
1632 sljit_s32 dst, sljit_sw dstw,
1633 sljit_s32 src, sljit_sw srcw)
1635 #if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)
1636 # define flags 0
1637 #else
1638 sljit_s32 flags = (GET_OPCODE(op) == SLJIT_CONV_F64_FROM_SW) << 21;
1639 #endif
1641 sljit_s32 dst_r = FAST_IS_REG(dst) ? dst : TMP_FREG1;
1643 if (FAST_IS_REG(src))
1644 FAIL_IF(push_inst(compiler, MTC1 | flags | T(src) | FS(TMP_FREG1), MOVABLE_INS));
1645 else if (src & SLJIT_MEM) {
1646 /* Load the integer value into a VFP register. */
1647 FAIL_IF(emit_op_mem2(compiler, ((flags) ? DOUBLE_DATA : SINGLE_DATA) | LOAD_DATA, FR(TMP_FREG1), src, srcw, dst, dstw));
1649 else {
1650 #if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
1651 if (GET_OPCODE(op) == SLJIT_CONV_F64_FROM_S32)
1652 srcw = (sljit_s32)srcw;
1653 #endif
1654 FAIL_IF(load_immediate(compiler, DR(TMP_REG1), srcw));
1655 FAIL_IF(push_inst(compiler, MTC1 | flags | T(TMP_REG1) | FS(TMP_FREG1), MOVABLE_INS));
1658 FAIL_IF(push_inst(compiler, CVT_S_S | flags | (4 << 21) | (((op & SLJIT_32) ^ SLJIT_32) >> 8) | FS(TMP_FREG1) | FD(dst_r), MOVABLE_INS));
1660 if (dst & SLJIT_MEM)
1661 return emit_op_mem2(compiler, FLOAT_DATA(op), FR(TMP_FREG1), dst, dstw, 0, 0);
1662 return SLJIT_SUCCESS;
1664 #if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)
1665 # undef flags
1666 #endif
1669 static SLJIT_INLINE sljit_s32 sljit_emit_fop1_cmp(struct sljit_compiler *compiler, sljit_s32 op,
1670 sljit_s32 src1, sljit_sw src1w,
1671 sljit_s32 src2, sljit_sw src2w)
1673 sljit_ins inst;
1675 if (src1 & SLJIT_MEM) {
1676 FAIL_IF(emit_op_mem2(compiler, FLOAT_DATA(op) | LOAD_DATA, FR(TMP_FREG1), src1, src1w, src2, src2w));
1677 src1 = TMP_FREG1;
1680 if (src2 & SLJIT_MEM) {
1681 FAIL_IF(emit_op_mem2(compiler, FLOAT_DATA(op) | LOAD_DATA, FR(TMP_FREG2), src2, src2w, 0, 0));
1682 src2 = TMP_FREG2;
1685 switch (GET_FLAG_TYPE(op)) {
1686 case SLJIT_EQUAL_F64:
1687 case SLJIT_NOT_EQUAL_F64:
1688 inst = C_UEQ_S;
1689 break;
1690 case SLJIT_LESS_F64:
1691 case SLJIT_GREATER_EQUAL_F64:
1692 inst = C_ULT_S;
1693 break;
1694 case SLJIT_GREATER_F64:
1695 case SLJIT_LESS_EQUAL_F64:
1696 inst = C_ULE_S;
1697 break;
1698 default:
1699 SLJIT_ASSERT(GET_FLAG_TYPE(op) == SLJIT_UNORDERED_F64 || GET_FLAG_TYPE(op) == SLJIT_ORDERED_F64);
1700 inst = C_UN_S;
1701 break;
1703 return push_inst(compiler, inst | FMT(op) | FT(src2) | FS(src1) | C_FD, UNMOVABLE_INS);
1706 SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fop1(struct sljit_compiler *compiler, sljit_s32 op,
1707 sljit_s32 dst, sljit_sw dstw,
1708 sljit_s32 src, sljit_sw srcw)
1710 sljit_s32 dst_r;
1712 CHECK_ERROR();
1713 compiler->cache_arg = 0;
1714 compiler->cache_argw = 0;
1716 SLJIT_COMPILE_ASSERT((SLJIT_32 == 0x100) && !(DOUBLE_DATA & 0x2), float_transfer_bit_error);
1717 SELECT_FOP1_OPERATION_WITH_CHECKS(compiler, op, dst, dstw, src, srcw);
1719 if (GET_OPCODE(op) == SLJIT_CONV_F64_FROM_F32)
1720 op ^= SLJIT_32;
1722 dst_r = FAST_IS_REG(dst) ? dst : TMP_FREG1;
1724 if (src & SLJIT_MEM) {
1725 FAIL_IF(emit_op_mem2(compiler, FLOAT_DATA(op) | LOAD_DATA, FR(dst_r), src, srcw, dst, dstw));
1726 src = dst_r;
1729 switch (GET_OPCODE(op)) {
1730 case SLJIT_MOV_F64:
1731 if (src != dst_r) {
1732 if (dst_r != TMP_FREG1)
1733 FAIL_IF(push_inst(compiler, MOV_S | FMT(op) | FS(src) | FD(dst_r), MOVABLE_INS));
1734 else
1735 dst_r = src;
1737 break;
1738 case SLJIT_NEG_F64:
1739 FAIL_IF(push_inst(compiler, NEG_S | FMT(op) | FS(src) | FD(dst_r), MOVABLE_INS));
1740 break;
1741 case SLJIT_ABS_F64:
1742 FAIL_IF(push_inst(compiler, ABS_S | FMT(op) | FS(src) | FD(dst_r), MOVABLE_INS));
1743 break;
1744 case SLJIT_CONV_F64_FROM_F32:
1745 FAIL_IF(push_inst(compiler, CVT_S_S | ((op & SLJIT_32) ? 1 : (1 << 21)) | FS(src) | FD(dst_r), MOVABLE_INS));
1746 op ^= SLJIT_32;
1747 break;
1750 if (dst & SLJIT_MEM)
1751 return emit_op_mem2(compiler, FLOAT_DATA(op), FR(dst_r), dst, dstw, 0, 0);
1752 return SLJIT_SUCCESS;
1755 SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fop2(struct sljit_compiler *compiler, sljit_s32 op,
1756 sljit_s32 dst, sljit_sw dstw,
1757 sljit_s32 src1, sljit_sw src1w,
1758 sljit_s32 src2, sljit_sw src2w)
1760 sljit_s32 dst_r, flags = 0;
1762 CHECK_ERROR();
1763 CHECK(check_sljit_emit_fop2(compiler, op, dst, dstw, src1, src1w, src2, src2w));
1764 ADJUST_LOCAL_OFFSET(dst, dstw);
1765 ADJUST_LOCAL_OFFSET(src1, src1w);
1766 ADJUST_LOCAL_OFFSET(src2, src2w);
1768 compiler->cache_arg = 0;
1769 compiler->cache_argw = 0;
1771 dst_r = FAST_IS_REG(dst) ? dst : TMP_FREG2;
1773 if (src1 & SLJIT_MEM) {
1774 if (getput_arg_fast(compiler, FLOAT_DATA(op) | LOAD_DATA, FR(TMP_FREG1), src1, src1w)) {
1775 FAIL_IF(compiler->error);
1776 src1 = TMP_FREG1;
1777 } else
1778 flags |= SLOW_SRC1;
1781 if (src2 & SLJIT_MEM) {
1782 if (getput_arg_fast(compiler, FLOAT_DATA(op) | LOAD_DATA, FR(TMP_FREG2), src2, src2w)) {
1783 FAIL_IF(compiler->error);
1784 src2 = TMP_FREG2;
1785 } else
1786 flags |= SLOW_SRC2;
1789 if ((flags & (SLOW_SRC1 | SLOW_SRC2)) == (SLOW_SRC1 | SLOW_SRC2)) {
1790 if (!can_cache(src1, src1w, src2, src2w) && can_cache(src1, src1w, dst, dstw)) {
1791 FAIL_IF(getput_arg(compiler, FLOAT_DATA(op) | LOAD_DATA, FR(TMP_FREG2), src2, src2w, src1, src1w));
1792 FAIL_IF(getput_arg(compiler, FLOAT_DATA(op) | LOAD_DATA, FR(TMP_FREG1), src1, src1w, dst, dstw));
1794 else {
1795 FAIL_IF(getput_arg(compiler, FLOAT_DATA(op) | LOAD_DATA, FR(TMP_FREG1), src1, src1w, src2, src2w));
1796 FAIL_IF(getput_arg(compiler, FLOAT_DATA(op) | LOAD_DATA, FR(TMP_FREG2), src2, src2w, dst, dstw));
1799 else if (flags & SLOW_SRC1)
1800 FAIL_IF(getput_arg(compiler, FLOAT_DATA(op) | LOAD_DATA, FR(TMP_FREG1), src1, src1w, dst, dstw));
1801 else if (flags & SLOW_SRC2)
1802 FAIL_IF(getput_arg(compiler, FLOAT_DATA(op) | LOAD_DATA, FR(TMP_FREG2), src2, src2w, dst, dstw));
1804 if (flags & SLOW_SRC1)
1805 src1 = TMP_FREG1;
1806 if (flags & SLOW_SRC2)
1807 src2 = TMP_FREG2;
1809 switch (GET_OPCODE(op)) {
1810 case SLJIT_ADD_F64:
1811 FAIL_IF(push_inst(compiler, ADD_S | FMT(op) | FT(src2) | FS(src1) | FD(dst_r), MOVABLE_INS));
1812 break;
1814 case SLJIT_SUB_F64:
1815 FAIL_IF(push_inst(compiler, SUB_S | FMT(op) | FT(src2) | FS(src1) | FD(dst_r), MOVABLE_INS));
1816 break;
1818 case SLJIT_MUL_F64:
1819 FAIL_IF(push_inst(compiler, MUL_S | FMT(op) | FT(src2) | FS(src1) | FD(dst_r), MOVABLE_INS));
1820 break;
1822 case SLJIT_DIV_F64:
1823 FAIL_IF(push_inst(compiler, DIV_S | FMT(op) | FT(src2) | FS(src1) | FD(dst_r), MOVABLE_INS));
1824 break;
1827 if (dst_r == TMP_FREG2)
1828 FAIL_IF(emit_op_mem2(compiler, FLOAT_DATA(op), FR(TMP_FREG2), dst, dstw, 0, 0));
1830 return SLJIT_SUCCESS;
1833 /* --------------------------------------------------------------------- */
1834 /* Other instructions */
1835 /* --------------------------------------------------------------------- */
1837 SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fast_enter(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw dstw)
1839 CHECK_ERROR();
1840 CHECK(check_sljit_emit_fast_enter(compiler, dst, dstw));
1841 ADJUST_LOCAL_OFFSET(dst, dstw);
1843 if (FAST_IS_REG(dst))
1844 return push_inst(compiler, ADDU_W | SA(RETURN_ADDR_REG) | TA(0) | D(dst), UNMOVABLE_INS);
1846 /* Memory. */
1847 FAIL_IF(emit_op_mem(compiler, WORD_DATA, RETURN_ADDR_REG, dst, dstw));
1848 compiler->delay_slot = UNMOVABLE_INS;
1849 return SLJIT_SUCCESS;
1852 /* --------------------------------------------------------------------- */
1853 /* Conditional instructions */
1854 /* --------------------------------------------------------------------- */
1856 SLJIT_API_FUNC_ATTRIBUTE struct sljit_label* sljit_emit_label(struct sljit_compiler *compiler)
1858 struct sljit_label *label;
1860 CHECK_ERROR_PTR();
1861 CHECK_PTR(check_sljit_emit_label(compiler));
1863 if (compiler->last_label && compiler->last_label->size == compiler->size)
1864 return compiler->last_label;
1866 label = (struct sljit_label*)ensure_abuf(compiler, sizeof(struct sljit_label));
1867 PTR_FAIL_IF(!label);
1868 set_label(label, compiler);
1869 compiler->delay_slot = UNMOVABLE_INS;
1870 return label;
1873 #if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)
1874 #define JUMP_LENGTH 4
1875 #else
1876 #define JUMP_LENGTH 8
1877 #endif
1879 #define BR_Z(src) \
1880 inst = BEQ | SA(src) | TA(0) | JUMP_LENGTH; \
1881 flags = IS_BIT26_COND; \
1882 delay_check = src;
1884 #define BR_NZ(src) \
1885 inst = BNE | SA(src) | TA(0) | JUMP_LENGTH; \
1886 flags = IS_BIT26_COND; \
1887 delay_check = src;
1889 #if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 6)
1891 #define BR_T() \
1892 inst = BC1NEZ; \
1893 flags = IS_BIT23_COND; \
1894 delay_check = FCSR_FCC;
1895 #define BR_F() \
1896 inst = BC1EQZ; \
1897 flags = IS_BIT23_COND; \
1898 delay_check = FCSR_FCC;
1900 #else /* SLJIT_MIPS_REV < 6 */
1902 #define BR_T() \
1903 inst = BC1T | JUMP_LENGTH; \
1904 flags = IS_BIT16_COND; \
1905 delay_check = FCSR_FCC;
1906 #define BR_F() \
1907 inst = BC1F | JUMP_LENGTH; \
1908 flags = IS_BIT16_COND; \
1909 delay_check = FCSR_FCC;
1911 #endif /* SLJIT_MIPS_REV >= 6 */
1913 SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_jump(struct sljit_compiler *compiler, sljit_s32 type)
1915 struct sljit_jump *jump;
1916 sljit_ins inst;
1917 sljit_s32 flags = 0;
1918 sljit_s32 delay_check = UNMOVABLE_INS;
1920 CHECK_ERROR_PTR();
1921 CHECK_PTR(check_sljit_emit_jump(compiler, type));
1923 jump = (struct sljit_jump*)ensure_abuf(compiler, sizeof(struct sljit_jump));
1924 PTR_FAIL_IF(!jump);
1925 set_jump(jump, compiler, type & SLJIT_REWRITABLE_JUMP);
1926 type &= 0xff;
1928 switch (type) {
1929 case SLJIT_EQUAL:
1930 BR_NZ(EQUAL_FLAG);
1931 break;
1932 case SLJIT_NOT_EQUAL:
1933 BR_Z(EQUAL_FLAG);
1934 break;
1935 case SLJIT_LESS:
1936 case SLJIT_GREATER:
1937 case SLJIT_SIG_LESS:
1938 case SLJIT_SIG_GREATER:
1939 case SLJIT_OVERFLOW:
1940 BR_Z(OTHER_FLAG);
1941 break;
1942 case SLJIT_GREATER_EQUAL:
1943 case SLJIT_LESS_EQUAL:
1944 case SLJIT_SIG_GREATER_EQUAL:
1945 case SLJIT_SIG_LESS_EQUAL:
1946 case SLJIT_NOT_OVERFLOW:
1947 BR_NZ(OTHER_FLAG);
1948 break;
1949 case SLJIT_NOT_EQUAL_F64:
1950 case SLJIT_GREATER_EQUAL_F64:
1951 case SLJIT_GREATER_F64:
1952 case SLJIT_ORDERED_F64:
1953 BR_T();
1954 break;
1955 case SLJIT_EQUAL_F64:
1956 case SLJIT_LESS_F64:
1957 case SLJIT_LESS_EQUAL_F64:
1958 case SLJIT_UNORDERED_F64:
1959 BR_F();
1960 break;
1961 default:
1962 /* Not conditional branch. */
1963 inst = 0;
1964 break;
1967 jump->flags |= flags;
1968 if (compiler->delay_slot == MOVABLE_INS || (compiler->delay_slot != UNMOVABLE_INS && compiler->delay_slot != delay_check))
1969 jump->flags |= IS_MOVABLE;
1971 if (inst)
1972 PTR_FAIL_IF(push_inst(compiler, inst, UNMOVABLE_INS));
1974 PTR_FAIL_IF(emit_const(compiler, TMP_REG2, 0));
1976 if (type <= SLJIT_JUMP)
1977 PTR_FAIL_IF(push_inst(compiler, JR | S(TMP_REG2), UNMOVABLE_INS));
1978 else {
1979 jump->flags |= IS_JAL;
1980 PTR_FAIL_IF(push_inst(compiler, JALR | S(TMP_REG2) | DA(RETURN_ADDR_REG), UNMOVABLE_INS));
1983 jump->addr = compiler->size;
1984 PTR_FAIL_IF(push_inst(compiler, NOP, UNMOVABLE_INS));
1985 return jump;
1988 #define RESOLVE_IMM1() \
1989 if (src1 & SLJIT_IMM) { \
1990 if (src1w) { \
1991 PTR_FAIL_IF(load_immediate(compiler, DR(TMP_REG1), src1w)); \
1992 src1 = TMP_REG1; \
1994 else \
1995 src1 = 0; \
1998 #define RESOLVE_IMM2() \
1999 if (src2 & SLJIT_IMM) { \
2000 if (src2w) { \
2001 PTR_FAIL_IF(load_immediate(compiler, DR(TMP_REG2), src2w)); \
2002 src2 = TMP_REG2; \
2004 else \
2005 src2 = 0; \
2008 SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_cmp(struct sljit_compiler *compiler, sljit_s32 type,
2009 sljit_s32 src1, sljit_sw src1w,
2010 sljit_s32 src2, sljit_sw src2w)
2012 struct sljit_jump *jump;
2013 sljit_s32 flags;
2014 sljit_ins inst;
2016 CHECK_ERROR_PTR();
2017 CHECK_PTR(check_sljit_emit_cmp(compiler, type, src1, src1w, src2, src2w));
2018 ADJUST_LOCAL_OFFSET(src1, src1w);
2019 ADJUST_LOCAL_OFFSET(src2, src2w);
2021 compiler->cache_arg = 0;
2022 compiler->cache_argw = 0;
2023 flags = ((type & SLJIT_32) ? INT_DATA : WORD_DATA) | LOAD_DATA;
2024 if (src1 & SLJIT_MEM) {
2025 PTR_FAIL_IF(emit_op_mem2(compiler, flags, DR(TMP_REG1), src1, src1w, src2, src2w));
2026 src1 = TMP_REG1;
2028 if (src2 & SLJIT_MEM) {
2029 PTR_FAIL_IF(emit_op_mem2(compiler, flags, DR(TMP_REG2), src2, src2w, 0, 0));
2030 src2 = TMP_REG2;
2033 jump = (struct sljit_jump*)ensure_abuf(compiler, sizeof(struct sljit_jump));
2034 PTR_FAIL_IF(!jump);
2035 set_jump(jump, compiler, type & SLJIT_REWRITABLE_JUMP);
2036 type &= 0xff;
2038 if (type <= SLJIT_NOT_EQUAL) {
2039 RESOLVE_IMM1();
2040 RESOLVE_IMM2();
2041 jump->flags |= IS_BIT26_COND;
2042 if (compiler->delay_slot == MOVABLE_INS || (compiler->delay_slot != UNMOVABLE_INS && compiler->delay_slot != DR(src1) && compiler->delay_slot != DR(src2)))
2043 jump->flags |= IS_MOVABLE;
2044 PTR_FAIL_IF(push_inst(compiler, (type == SLJIT_EQUAL ? BNE : BEQ) | S(src1) | T(src2) | JUMP_LENGTH, UNMOVABLE_INS));
2046 else if (type >= SLJIT_SIG_LESS && (((src1 & SLJIT_IMM) && (src1w == 0)) || ((src2 & SLJIT_IMM) && (src2w == 0)))) {
2047 inst = NOP;
2048 if ((src1 & SLJIT_IMM) && (src1w == 0)) {
2049 RESOLVE_IMM2();
2050 switch (type) {
2051 case SLJIT_SIG_LESS:
2052 inst = BLEZ;
2053 jump->flags |= IS_BIT26_COND;
2054 break;
2055 case SLJIT_SIG_GREATER_EQUAL:
2056 inst = BGTZ;
2057 jump->flags |= IS_BIT26_COND;
2058 break;
2059 case SLJIT_SIG_GREATER:
2060 inst = BGEZ;
2061 jump->flags |= IS_BIT16_COND;
2062 break;
2063 case SLJIT_SIG_LESS_EQUAL:
2064 inst = BLTZ;
2065 jump->flags |= IS_BIT16_COND;
2066 break;
2068 src1 = src2;
2070 else {
2071 RESOLVE_IMM1();
2072 switch (type) {
2073 case SLJIT_SIG_LESS:
2074 inst = BGEZ;
2075 jump->flags |= IS_BIT16_COND;
2076 break;
2077 case SLJIT_SIG_GREATER_EQUAL:
2078 inst = BLTZ;
2079 jump->flags |= IS_BIT16_COND;
2080 break;
2081 case SLJIT_SIG_GREATER:
2082 inst = BLEZ;
2083 jump->flags |= IS_BIT26_COND;
2084 break;
2085 case SLJIT_SIG_LESS_EQUAL:
2086 inst = BGTZ;
2087 jump->flags |= IS_BIT26_COND;
2088 break;
2091 PTR_FAIL_IF(push_inst(compiler, inst | S(src1) | JUMP_LENGTH, UNMOVABLE_INS));
2093 else {
2094 if (type == SLJIT_LESS || type == SLJIT_GREATER_EQUAL || type == SLJIT_SIG_LESS || type == SLJIT_SIG_GREATER_EQUAL) {
2095 RESOLVE_IMM1();
2096 if ((src2 & SLJIT_IMM) && src2w <= SIMM_MAX && src2w >= SIMM_MIN)
2097 PTR_FAIL_IF(push_inst(compiler, (type <= SLJIT_LESS_EQUAL ? SLTIU : SLTI) | S(src1) | T(TMP_REG1) | IMM(src2w), DR(TMP_REG1)));
2098 else {
2099 RESOLVE_IMM2();
2100 PTR_FAIL_IF(push_inst(compiler, (type <= SLJIT_LESS_EQUAL ? SLTU : SLT) | S(src1) | T(src2) | D(TMP_REG1), DR(TMP_REG1)));
2102 type = (type == SLJIT_LESS || type == SLJIT_SIG_LESS) ? SLJIT_NOT_EQUAL : SLJIT_EQUAL;
2104 else {
2105 RESOLVE_IMM2();
2106 if ((src1 & SLJIT_IMM) && src1w <= SIMM_MAX && src1w >= SIMM_MIN)
2107 PTR_FAIL_IF(push_inst(compiler, (type <= SLJIT_LESS_EQUAL ? SLTIU : SLTI) | S(src2) | T(TMP_REG1) | IMM(src1w), DR(TMP_REG1)));
2108 else {
2109 RESOLVE_IMM1();
2110 PTR_FAIL_IF(push_inst(compiler, (type <= SLJIT_LESS_EQUAL ? SLTU : SLT) | S(src2) | T(src1) | D(TMP_REG1), DR(TMP_REG1)));
2112 type = (type == SLJIT_GREATER || type == SLJIT_SIG_GREATER) ? SLJIT_NOT_EQUAL : SLJIT_EQUAL;
2115 jump->flags |= IS_BIT26_COND;
2116 PTR_FAIL_IF(push_inst(compiler, (type == SLJIT_EQUAL ? BNE : BEQ) | S(TMP_REG1) | TA(0) | JUMP_LENGTH, UNMOVABLE_INS));
2119 PTR_FAIL_IF(emit_const(compiler, TMP_REG2, 0));
2120 PTR_FAIL_IF(push_inst(compiler, JR | S(TMP_REG2), UNMOVABLE_INS));
2121 jump->addr = compiler->size;
2122 PTR_FAIL_IF(push_inst(compiler, NOP, UNMOVABLE_INS));
2123 return jump;
2126 #undef RESOLVE_IMM1
2127 #undef RESOLVE_IMM2
2129 #undef JUMP_LENGTH
2130 #undef BR_Z
2131 #undef BR_NZ
2132 #undef BR_T
2133 #undef BR_F
2135 #undef FLOAT_DATA
2136 #undef FMT
2138 SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_ijump(struct sljit_compiler *compiler, sljit_s32 type, sljit_s32 src, sljit_sw srcw)
2140 struct sljit_jump *jump = NULL;
2142 CHECK_ERROR();
2143 CHECK(check_sljit_emit_ijump(compiler, type, src, srcw));
2144 ADJUST_LOCAL_OFFSET(src, srcw);
2146 if (src & SLJIT_IMM) {
2147 jump = (struct sljit_jump*)ensure_abuf(compiler, sizeof(struct sljit_jump));
2148 FAIL_IF(!jump);
2149 set_jump(jump, compiler, JUMP_ADDR | ((type >= SLJIT_FAST_CALL) ? IS_JAL : 0));
2150 jump->u.target = srcw;
2152 if (compiler->delay_slot != UNMOVABLE_INS)
2153 jump->flags |= IS_MOVABLE;
2155 FAIL_IF(emit_const(compiler, TMP_REG2, 0));
2156 src = TMP_REG2;
2158 else if (src & SLJIT_MEM) {
2159 FAIL_IF(emit_op_mem(compiler, WORD_DATA | LOAD_DATA, DR(TMP_REG2), src, srcw));
2160 src = TMP_REG2;
2163 FAIL_IF(push_inst(compiler, JR | S(src), UNMOVABLE_INS));
2164 if (jump)
2165 jump->addr = compiler->size;
2166 FAIL_IF(push_inst(compiler, NOP, UNMOVABLE_INS));
2167 return SLJIT_SUCCESS;
2170 SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_flags(struct sljit_compiler *compiler, sljit_s32 op,
2171 sljit_s32 dst, sljit_sw dstw,
2172 sljit_s32 type)
2174 sljit_s32 src_ar, dst_ar;
2175 sljit_s32 saved_op = op;
2176 #if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)
2177 sljit_s32 mem_type = WORD_DATA;
2178 #else
2179 sljit_s32 mem_type = ((op & SLJIT_32) || op == SLJIT_MOV32) ? (INT_DATA | SIGNED_DATA) : WORD_DATA;
2180 #endif
2182 CHECK_ERROR();
2183 CHECK(check_sljit_emit_op_flags(compiler, op, dst, dstw, type));
2184 ADJUST_LOCAL_OFFSET(dst, dstw);
2186 op = GET_OPCODE(op);
2187 dst_ar = DR((op < SLJIT_ADD && FAST_IS_REG(dst)) ? dst : TMP_REG2);
2189 compiler->cache_arg = 0;
2190 compiler->cache_argw = 0;
2192 if (op >= SLJIT_ADD && (dst & SLJIT_MEM))
2193 FAIL_IF(emit_op_mem2(compiler, mem_type | LOAD_DATA, DR(TMP_REG1), dst, dstw, dst, dstw));
2195 switch (type & 0xff) {
2196 case SLJIT_EQUAL:
2197 case SLJIT_NOT_EQUAL:
2198 FAIL_IF(push_inst(compiler, SLTIU | SA(EQUAL_FLAG) | TA(dst_ar) | IMM(1), dst_ar));
2199 src_ar = dst_ar;
2200 break;
2201 case SLJIT_OVERFLOW:
2202 case SLJIT_NOT_OVERFLOW:
2203 if (compiler->status_flags_state & SLJIT_CURRENT_FLAGS_ADD_SUB) {
2204 src_ar = OTHER_FLAG;
2205 break;
2207 FAIL_IF(push_inst(compiler, SLTIU | SA(OTHER_FLAG) | TA(dst_ar) | IMM(1), dst_ar));
2208 src_ar = dst_ar;
2209 type ^= 0x1; /* Flip type bit for the XORI below. */
2210 break;
2211 case SLJIT_GREATER_F64:
2212 case SLJIT_LESS_EQUAL_F64:
2213 type ^= 0x1; /* Flip type bit for the XORI below. */
2214 case SLJIT_EQUAL_F64:
2215 case SLJIT_NOT_EQUAL_F64:
2216 case SLJIT_LESS_F64:
2217 case SLJIT_GREATER_EQUAL_F64:
2218 case SLJIT_UNORDERED_F64:
2219 case SLJIT_ORDERED_F64:
2220 #if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 6)
2221 FAIL_IF(push_inst(compiler, MFC1 | TA(dst_ar) | FS(TMP_FREG3), dst_ar));
2222 #else /* SLJIT_MIPS_REV < 6 */
2223 FAIL_IF(push_inst(compiler, CFC1 | TA(dst_ar) | DA(FCSR_REG), dst_ar));
2224 #endif /* SLJIT_MIPS_REV >= 6 */
2225 FAIL_IF(push_inst(compiler, SRL | TA(dst_ar) | DA(dst_ar) | SH_IMM(23), dst_ar));
2226 FAIL_IF(push_inst(compiler, ANDI | SA(dst_ar) | TA(dst_ar) | IMM(1), dst_ar));
2227 src_ar = dst_ar;
2228 break;
2230 default:
2231 src_ar = OTHER_FLAG;
2232 break;
2235 if (type & 0x1) {
2236 FAIL_IF(push_inst(compiler, XORI | SA(src_ar) | TA(dst_ar) | IMM(1), dst_ar));
2237 src_ar = dst_ar;
2240 if (op < SLJIT_ADD) {
2241 if (dst & SLJIT_MEM)
2242 return emit_op_mem(compiler, mem_type, src_ar, dst, dstw);
2244 if (src_ar != dst_ar)
2245 return push_inst(compiler, ADDU_W | SA(src_ar) | TA(0) | DA(dst_ar), dst_ar);
2246 return SLJIT_SUCCESS;
2249 /* OTHER_FLAG cannot be specified as src2 argument at the moment. */
2250 if (DR(TMP_REG2) != src_ar)
2251 FAIL_IF(push_inst(compiler, ADDU_W | SA(src_ar) | TA(0) | D(TMP_REG2), DR(TMP_REG2)));
2253 mem_type |= CUMULATIVE_OP | LOGICAL_OP | IMM_OP | ALT_KEEP_CACHE;
2255 if (dst & SLJIT_MEM)
2256 return emit_op(compiler, saved_op, mem_type, dst, dstw, TMP_REG1, 0, TMP_REG2, 0);
2257 return emit_op(compiler, saved_op, mem_type, dst, dstw, dst, dstw, TMP_REG2, 0);
2260 SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_cmov(struct sljit_compiler *compiler, sljit_s32 type,
2261 sljit_s32 dst_reg,
2262 sljit_s32 src, sljit_sw srcw)
2264 #if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 1 && SLJIT_MIPS_REV < 6)
2265 sljit_ins ins;
2266 #endif /* SLJIT_MIPS_REV >= 1 && SLJIT_MIPS_REV < 6 */
2268 CHECK_ERROR();
2269 CHECK(check_sljit_emit_cmov(compiler, type, dst_reg, src, srcw));
2271 #if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 1 && SLJIT_MIPS_REV < 6)
2273 if (SLJIT_UNLIKELY(src & SLJIT_IMM)) {
2274 #if (defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64)
2275 if (dst_reg & SLJIT_32)
2276 srcw = (sljit_s32)srcw;
2277 #endif
2278 FAIL_IF(load_immediate(compiler, DR(TMP_REG1), srcw));
2279 src = TMP_REG1;
2280 srcw = 0;
2283 dst_reg &= ~SLJIT_32;
2285 switch (type & 0xff) {
2286 case SLJIT_EQUAL:
2287 ins = MOVZ | TA(EQUAL_FLAG);
2288 break;
2289 case SLJIT_NOT_EQUAL:
2290 ins = MOVN | TA(EQUAL_FLAG);
2291 break;
2292 case SLJIT_LESS:
2293 case SLJIT_GREATER:
2294 case SLJIT_SIG_LESS:
2295 case SLJIT_SIG_GREATER:
2296 case SLJIT_OVERFLOW:
2297 ins = MOVN | TA(OTHER_FLAG);
2298 break;
2299 case SLJIT_GREATER_EQUAL:
2300 case SLJIT_LESS_EQUAL:
2301 case SLJIT_SIG_GREATER_EQUAL:
2302 case SLJIT_SIG_LESS_EQUAL:
2303 case SLJIT_NOT_OVERFLOW:
2304 ins = MOVZ | TA(OTHER_FLAG);
2305 break;
2306 case SLJIT_EQUAL_F64:
2307 case SLJIT_LESS_F64:
2308 case SLJIT_LESS_EQUAL_F64:
2309 case SLJIT_UNORDERED_F64:
2310 ins = MOVT;
2311 break;
2312 case SLJIT_NOT_EQUAL_F64:
2313 case SLJIT_GREATER_EQUAL_F64:
2314 case SLJIT_GREATER_F64:
2315 case SLJIT_ORDERED_F64:
2316 ins = MOVF;
2317 break;
2318 default:
2319 ins = MOVZ | TA(OTHER_FLAG);
2320 SLJIT_UNREACHABLE();
2321 break;
2324 return push_inst(compiler, ins | S(src) | D(dst_reg), DR(dst_reg));
2326 #else /* SLJIT_MIPS_REV < 1 || SLJIT_MIPS_REV >= 6 */
2327 return sljit_emit_cmov_generic(compiler, type, dst_reg, src, srcw);
2328 #endif /* SLJIT_MIPS_REV >= 1 */
2331 SLJIT_API_FUNC_ATTRIBUTE struct sljit_const* sljit_emit_const(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw dstw, sljit_sw init_value)
2333 struct sljit_const *const_;
2334 sljit_s32 dst_r;
2336 CHECK_ERROR_PTR();
2337 CHECK_PTR(check_sljit_emit_const(compiler, dst, dstw, init_value));
2338 ADJUST_LOCAL_OFFSET(dst, dstw);
2340 const_ = (struct sljit_const*)ensure_abuf(compiler, sizeof(struct sljit_const));
2341 PTR_FAIL_IF(!const_);
2342 set_const(const_, compiler);
2344 dst_r = FAST_IS_REG(dst) ? dst : TMP_REG2;
2345 PTR_FAIL_IF(emit_const(compiler, dst_r, init_value));
2347 if (dst & SLJIT_MEM)
2348 PTR_FAIL_IF(emit_op(compiler, SLJIT_MOV, WORD_DATA, dst, dstw, TMP_REG1, 0, TMP_REG2, 0));
2350 return const_;
2353 SLJIT_API_FUNC_ATTRIBUTE struct sljit_put_label* sljit_emit_put_label(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw dstw)
2355 struct sljit_put_label *put_label;
2356 sljit_s32 dst_r;
2358 CHECK_ERROR_PTR();
2359 CHECK_PTR(check_sljit_emit_put_label(compiler, dst, dstw));
2360 ADJUST_LOCAL_OFFSET(dst, dstw);
2362 put_label = (struct sljit_put_label*)ensure_abuf(compiler, sizeof(struct sljit_put_label));
2363 PTR_FAIL_IF(!put_label);
2364 set_put_label(put_label, compiler, 0);
2366 dst_r = FAST_IS_REG(dst) ? dst : TMP_REG2;
2367 #if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)
2368 PTR_FAIL_IF(emit_const(compiler, dst_r, 0));
2369 #else
2370 PTR_FAIL_IF(push_inst(compiler, dst_r, UNMOVABLE_INS));
2371 compiler->size += 5;
2372 #endif
2374 if (dst & SLJIT_MEM)
2375 PTR_FAIL_IF(emit_op(compiler, SLJIT_MOV, WORD_DATA, dst, dstw, TMP_REG1, 0, TMP_REG2, 0));
2377 return put_label;