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
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. */
71 /* Return address register. */
72 #define RETURN_ADDR_REG 31
74 /* Flags are kept in volatile registers. */
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
94 static const sljit_u8 freg_map
[SLJIT_NUMBER_OF_FLOAT_REGISTERS
+ 4] = {
95 0, 0, 13, 14, 15, 16, 17, 12, 18, 10
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)
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))
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 */
146 #define BGEZ (HI(1) | (1 << 16))
149 #define BLTZ (HI(1) | (0 << 16))
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))
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))
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 */
209 #define LDC1 (HI(53))
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))
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))
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)
278 #define ADDIU_W ADDIU
283 #define ADDIU_W DADDIU
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));
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
)
311 #if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 6)
312 if (flags
& IS_BIT23_COND
)
314 #endif /* SLJIT_MIPS_REV >= 6 */
318 static SLJIT_INLINE sljit_ins
* detect_jump_type(struct sljit_jump
*jump
, sljit_ins
*code_ptr
, sljit_ins
*code
, sljit_sw executable_offset
)
321 sljit_uw target_addr
;
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
))
329 if (jump
->flags
& SLJIT_REWRITABLE_JUMP
)
333 if (jump
->flags
& JUMP_ADDR
)
334 target_addr
= jump
->u
.target
;
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
)
344 #if (defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64)
345 if (jump
->flags
& IS_CALL
)
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
)) {
357 inst
[-1] = (jump
->flags
& IS_JAL
) ? BAL
: B
;
358 jump
->addr
-= sizeof(sljit_ins
);
361 saved_inst
= inst
[0];
363 inst
[-1] = saved_inst
^ invert_branch(jump
->flags
);
364 jump
->addr
-= 2 * sizeof(sljit_ins
);
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
;
378 inst
[0] ^= invert_branch(jump
->flags
);
380 jump
->addr
-= sizeof(sljit_ins
);
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];
390 inst
[-1] = (saved_inst
& 0xffff0000) | 3;
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;
401 jump
->addr
+= sizeof(sljit_ins
);
407 if ((jump
->flags
& IS_MOVABLE
) && (target_addr
& ~(sljit_uw
)0xfffffff) == (jump
->addr
& ~(sljit_uw
)0xfffffff)) {
408 jump
->flags
|= PATCH_J
;
410 inst
[-1] = (jump
->flags
& IS_JAL
) ? JAL
: J
;
411 jump
->addr
-= sizeof(sljit_ins
);
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
;
423 #if (defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64)
425 if (target_addr
<= 0x7fffffff) {
426 jump
->flags
|= PATCH_ABS32
;
427 if (jump
->flags
& IS_COND
) {
435 if (target_addr
<= 0x7fffffffffffl
) {
436 jump
->flags
|= PATCH_ABS48
;
437 if (jump
->flags
& IS_COND
) {
451 static __attribute__ ((noinline
)) void sljit_cache_flush(void* code
, void* code_ptr
)
453 SLJIT_CACHE_FLUSH(code
, code_ptr
);
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;
466 if (max_label
< 0x800000000000l
) {
467 put_label
->flags
= 1;
471 put_label
->flags
= 2;
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);
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);
501 inst
[1] = ORI
| S(reg
) | T(reg
) | IMM(addr
& 0xffff);
506 SLJIT_API_FUNC_ATTRIBUTE
void* sljit_generate_code(struct sljit_compiler
*compiler
)
508 struct sljit_memory_fragment
*buf
;
515 sljit_sw executable_offset
;
518 struct sljit_label
*label
;
519 struct sljit_jump
*jump
;
520 struct sljit_const
*const_
;
521 struct sljit_put_label
*put_label
;
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
);
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
;
542 buf_ptr
= (sljit_ins
*)buf
->memory
;
543 buf_end
= buf_ptr
+ (buf
->used_size
>> 2);
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
);
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);
562 jump
->addr
= (sljit_uw
)(code_ptr
- 7);
564 code_ptr
= detect_jump_type(jump
, code_ptr
, code
, executable_offset
);
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
));
578 put_label
= put_label
->next
;
580 next_addr
= compute_next_addr(label
, jump
, const_
, put_label
);
584 } while (buf_ptr
< buf_end
);
589 if (label
&& label
->size
== word_count
) {
590 label
->addr
= (sljit_uw
)code_ptr
;
591 label
->size
= (sljit_uw
)(code_ptr
- code
);
595 SLJIT_ASSERT(!label
);
597 SLJIT_ASSERT(!const_
);
598 SLJIT_ASSERT(!put_label
);
599 SLJIT_ASSERT(code_ptr
- code
<= (sljit_sw
)compiler
->size
);
601 jump
= compiler
->jumps
;
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);
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;
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;
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;
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;
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;
653 put_label
= compiler
->put_labels
;
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;
663 put_label_set(put_label
);
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
);
676 SLJIT_CACHE_FLUSH(code
, code_ptr
);
678 /* GCC workaround for invalid code generation with -O2. */
679 sljit_cache_flush(code
, code_ptr
);
681 SLJIT_UPDATE_WX_FLAGS(code
, code_ptr
, 1);
685 SLJIT_API_FUNC_ATTRIBUTE sljit_s32
sljit_has_cpu_feature(sljit_s32 feature_type
)
687 #if defined(__GNUC__) && !defined(SLJIT_IS_FPU_AVAILABLE)
689 #endif /* __GNUC__ && !SLJIT_IS_FPU_AVAILABLE */
691 switch (feature_type
) {
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;
699 #error "FIR check is not implemented for this architecture"
701 case SLJIT_HAS_ZERO_REGISTER
:
704 #if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 1)
707 case SLJIT_HAS_PREFETCH
:
709 #endif /* SLJIT_MIPS_REV >= 1 */
716 /* --------------------------------------------------------------------- */
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 */
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
754 #define STACK_STORE SD
755 #define STACK_LOAD LD
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"
764 #include "sljitNativeMIPS_64.c"
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
)
772 sljit_s32 i
, tmp
, offs
;
773 sljit_s32 arg_count
, word_arg_count
, float_arg_count
;
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;
783 local_size
= (local_size
+ 31) & ~0x1f;
785 compiler
->local_size
= local_size
;
787 if (local_size
<= -SIMM_MIN
) {
789 FAIL_IF(push_inst(compiler
, ADDIU_W
| S(SLJIT_SP
) | T(SLJIT_SP
) | IMM(-local_size
), DR(SLJIT_SP
)));
791 offs
= local_size
- SSIZE_OF(sw
);
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
)));
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
;
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. */
828 switch (arg_types
& SLJIT_ARG_MASK
) {
829 case SLJIT_ARG_TYPE_F64
:
831 if ((arg_count
& 0x1) != 0)
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
));
841 FAIL_IF(push_inst(compiler
, LDC1
| base
| FT(float_arg_count
) | IMM(local_size
+ (arg_count
<< 2)), MOVABLE_INS
));
844 case SLJIT_ARG_TYPE_F32
:
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
));
853 FAIL_IF(push_inst(compiler
, LWC1
| base
| FT(float_arg_count
) | IMM(local_size
+ (arg_count
<< 2)), MOVABLE_INS
));
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
)));
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
)));
866 arg_types
>>= SLJIT_ARG_SHIFT
;
869 compiler
->args_size
= (sljit_uw
)arg_count
<< 2;
870 #else /* !SLJIT_CONFIG_MIPS_32 */
873 switch (arg_types
& SLJIT_ARG_MASK
) {
874 case SLJIT_ARG_TYPE_F64
:
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
));
881 case SLJIT_ARG_TYPE_F32
:
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
));
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
)));
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
)
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;
912 compiler
->local_size
= (local_size
+ 31) & ~0x1f;
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
);
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
;
943 if (tmp
< frame_size
) {
944 offs
= frame_size
- tmp
;
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
)));
953 SLJIT_ASSERT(local_size
>= frame_size
);
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
);
977 return SLJIT_SUCCESS
;
980 SLJIT_API_FUNC_ATTRIBUTE sljit_s32
sljit_emit_return_void(struct sljit_compiler
*compiler
)
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
);
996 /* --------------------------------------------------------------------- */
998 /* --------------------------------------------------------------------- */
1000 #if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)
1001 #define ARCH_32_64(a, b) a
1003 #define ARCH_32_64(a, b) b
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 */,
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
))
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
));
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
) {
1062 if (argw
&& argw
== next_argw
&& (arg
== next_arg
|| (arg
& OFFS_REG_MASK
) == (next_arg
& OFFS_REG_MASK
)))
1067 if (arg
== next_arg
) {
1068 if (((next_argw
- argw
) <= SIMM_MAX
&& (next_argw
- argw
) >= SIMM_MIN
))
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
)) {
1087 if ((flags
& MEM_MASK
) <= GPR_REG
&& (flags
& LOAD_DATA
)) {
1089 delay_slot
= reg_ar
;
1092 tmp_ar
= DR(TMP_REG1
);
1093 delay_slot
= MOVABLE_INS
;
1095 base
= arg
& REG_MASK
;
1097 if (SLJIT_UNLIKELY(arg
& OFFS_REG_MASK
)) {
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
);
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
)));
1147 compiler
->cache_arg
= SLJIT_MEM
;
1148 FAIL_IF(load_immediate(compiler
, DR(TMP_REG3
), argw
));
1150 compiler
->cache_argw
= argw
;
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
)) {
1174 delay_slot
= reg_ar
;
1177 tmp_ar
= DR(TMP_REG1
);
1178 delay_slot
= MOVABLE_INS
;
1180 base
= arg
& REG_MASK
;
1182 if (SLJIT_UNLIKELY(arg
& OFFS_REG_MASK
)) {
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
));
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
));
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
;
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
)) {
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
))
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
))) {
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
))) {
1255 /* And swap arguments. */
1259 /* src2w = src2_r unneeded. */
1265 if (FAST_IS_REG(src1
)) {
1267 flags
|= REG1_SOURCE
;
1269 else if (src1
& SLJIT_IMM
) {
1271 FAIL_IF(load_immediate(compiler
, DR(TMP_REG1
), src1w
));
1278 if (getput_arg_fast(compiler
, flags
| LOAD_DATA
, DR(TMP_REG1
), src1
, src1w
))
1279 FAIL_IF(compiler
->error
);
1286 if (FAST_IS_REG(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
)) {
1295 FAIL_IF(load_immediate(compiler
, DR(sugg_src2_r
), src2w
));
1296 src2_r
= sugg_src2_r
;
1300 if (flags
& MOVE_OP
) {
1301 if (dst
& SLJIT_MEM
)
1310 if (getput_arg_fast(compiler
, flags
| LOAD_DATA
, DR(sugg_src2_r
), src2
, src2w
))
1311 FAIL_IF(compiler
->error
);
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
));
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
;
1353 CHECK(check_sljit_emit_op0(compiler
, op
));
1355 op
= GET_OPCODE(op
);
1357 case SLJIT_BREAKPOINT
:
1358 return push_inst(compiler
, BREAK
, UNMOVABLE_INS
);
1360 return push_inst(compiler
, NOP
, UNMOVABLE_INS
);
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
:
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)
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
)));
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)
1410 FAIL_IF(push_inst(compiler
, ((op
| 0x2) == SLJIT_DIV_UW
? DIVU
: DIV
) | S(SLJIT_R0
) | T(SLJIT_R1
), MOVABLE_INS
));
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 */
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
);
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;
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)
1463 flags
= INT_DATA
| SIGNED_DATA
;
1466 switch (GET_OPCODE(op
)) {
1468 #if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)
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)
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
);
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
);
1486 return emit_op(compiler
, op
, BYTE_DATA
| MOVE_OP
, dst
, dstw
, TMP_REG1
, 0, src
, (src
& SLJIT_IMM
) ? (sljit_u8
)srcw
: srcw
);
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
);
1492 return emit_op(compiler
, op
, HALF_DATA
| MOVE_OP
, dst
, dstw
, TMP_REG1
, 0, src
, (src
& SLJIT_IMM
) ? (sljit_u16
)srcw
: srcw
);
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
);
1498 return emit_op(compiler
, op
, flags
, dst
, dstw
, TMP_REG1
, 0, src
, srcw
);
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
);
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;
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
;
1535 switch (GET_OPCODE(op
)) {
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
);
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
);
1547 compiler
->status_flags_state
= 0;
1548 return emit_op(compiler
, op
, flags
| CUMULATIVE_OP
, dst
, dstw
, src1
, src1w
, src2
, src2w
);
1553 return emit_op(compiler
, op
, flags
| CUMULATIVE_OP
| LOGICAL_OP
| IMM_OP
, dst
, dstw
, src1
, src1w
, src2
, src2w
);
1558 #if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)
1559 if (src2
& SLJIT_IMM
)
1562 if (src2
& SLJIT_IMM
) {
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
)
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;
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
)
1594 CHECK(check_sljit_emit_op_src(compiler
, op
, src
, srcw
));
1595 ADJUST_LOCAL_OFFSET(src
, srcw
);
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
));
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
));
1634 SLJIT_API_FUNC_ATTRIBUTE sljit_s32
sljit_emit_op_custom(struct sljit_compiler
*compiler
,
1635 void *instruction
, sljit_u32 size
)
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
1657 sljit_u32 flags
= (GET_OPCODE(op
) == SLJIT_CONV_SW_FROM_F64
) << 21;
1660 if (src
& SLJIT_MEM
) {
1661 FAIL_IF(emit_op_mem2(compiler
, FLOAT_DATA(op
) | LOAD_DATA
, FR(TMP_FREG1
), src
, srcw
, dst
, dstw
));
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)
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
1685 sljit_u32 flags
= (GET_OPCODE(op
) == SLJIT_CONV_F64_FROM_SW
) << 21;
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
));
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
;
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)
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
)
1722 if (src1
& SLJIT_MEM
) {
1723 FAIL_IF(emit_op_mem2(compiler
, FLOAT_DATA(op
) | LOAD_DATA
, FR(TMP_FREG1
), src1
, src1w
, src2
, src2w
));
1727 if (src2
& SLJIT_MEM
) {
1728 FAIL_IF(emit_op_mem2(compiler
, FLOAT_DATA(op
) | LOAD_DATA
, FR(TMP_FREG2
), src2
, src2w
, 0, 0));
1732 switch (GET_FLAG_TYPE(op
)) {
1733 case SLJIT_EQUAL_F64
:
1734 case SLJIT_NOT_EQUAL_F64
:
1737 case SLJIT_LESS_F64
:
1738 case SLJIT_GREATER_EQUAL_F64
:
1741 case SLJIT_GREATER_F64
:
1742 case SLJIT_LESS_EQUAL_F64
:
1746 SLJIT_ASSERT(GET_FLAG_TYPE(op
) == SLJIT_UNORDERED_F64
|| GET_FLAG_TYPE(op
) == SLJIT_ORDERED_F64
);
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
)
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
)
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
));
1776 switch (GET_OPCODE(op
)) {
1779 if (dst_r
!= TMP_FREG1
)
1780 FAIL_IF(push_inst(compiler
, MOV_S
| FMT(op
) | FS(src
) | FD(dst_r
), MOVABLE_INS
));
1786 FAIL_IF(push_inst(compiler
, NEG_S
| FMT(op
) | FS(src
) | FD(dst_r
), MOVABLE_INS
));
1789 FAIL_IF(push_inst(compiler
, ABS_S
| FMT(op
) | FS(src
) | FD(dst_r
), MOVABLE_INS
));
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
));
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;
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
);
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
);
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
));
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
)
1853 if (flags
& SLOW_SRC2
)
1856 switch (GET_OPCODE(op
)) {
1858 FAIL_IF(push_inst(compiler
, ADD_S
| FMT(op
) | FT(src2
) | FS(src1
) | FD(dst_r
), MOVABLE_INS
));
1862 FAIL_IF(push_inst(compiler
, SUB_S
| FMT(op
) | FT(src2
) | FS(src1
) | FD(dst_r
), MOVABLE_INS
));
1866 FAIL_IF(push_inst(compiler
, MUL_S
| FMT(op
) | FT(src2
) | FS(src1
) | FD(dst_r
), MOVABLE_INS
));
1870 FAIL_IF(push_inst(compiler
, DIV_S
| FMT(op
) | FT(src2
) | FS(src1
) | FD(dst_r
), MOVABLE_INS
));
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
)
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
);
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
;
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
;
1920 #if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)
1921 #define JUMP_LENGTH 4
1923 #define JUMP_LENGTH 8
1927 inst = BEQ | SA(src) | TA(0) | JUMP_LENGTH; \
1928 flags = IS_BIT26_COND; \
1931 #define BR_NZ(src) \
1932 inst = BNE | SA(src) | TA(0) | JUMP_LENGTH; \
1933 flags = IS_BIT26_COND; \
1936 #if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 6)
1940 flags = IS_BIT23_COND; \
1941 delay_check = FCSR_FCC;
1944 flags = IS_BIT23_COND; \
1945 delay_check = FCSR_FCC;
1947 #else /* SLJIT_MIPS_REV < 6 */
1950 inst = BC1T | JUMP_LENGTH; \
1951 flags = IS_BIT16_COND; \
1952 delay_check = FCSR_FCC;
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
;
1964 sljit_u32 flags
= 0;
1965 sljit_s32 delay_check
= UNMOVABLE_INS
;
1968 CHECK_PTR(check_sljit_emit_jump(compiler
, type
));
1970 jump
= (struct sljit_jump
*)ensure_abuf(compiler
, sizeof(struct sljit_jump
));
1972 set_jump(jump
, compiler
, type
& SLJIT_REWRITABLE_JUMP
);
1979 case SLJIT_NOT_EQUAL
:
1984 case SLJIT_SIG_LESS
:
1985 case SLJIT_SIG_GREATER
:
1986 case SLJIT_OVERFLOW
:
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
:
1996 case SLJIT_NOT_EQUAL_F64
:
1997 case SLJIT_GREATER_EQUAL_F64
:
1998 case SLJIT_GREATER_F64
:
1999 case SLJIT_ORDERED_F64
:
2002 case SLJIT_EQUAL_F64
:
2003 case SLJIT_LESS_F64
:
2004 case SLJIT_LESS_EQUAL_F64
:
2005 case SLJIT_UNORDERED_F64
:
2009 /* Not conditional branch. */
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
;
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
));
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
));
2035 #define RESOLVE_IMM1() \
2036 if (src1 & SLJIT_IMM) { \
2038 PTR_FAIL_IF(load_immediate(compiler, DR(TMP_REG1), src1w)); \
2045 #define RESOLVE_IMM2() \
2046 if (src2 & SLJIT_IMM) { \
2048 PTR_FAIL_IF(load_immediate(compiler, DR(TMP_REG2), src2w)); \
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
;
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
));
2075 if (src2
& SLJIT_MEM
) {
2076 PTR_FAIL_IF(emit_op_mem2(compiler
, flags
, DR(TMP_REG2
), src2
, src2w
, 0, 0));
2080 jump
= (struct sljit_jump
*)ensure_abuf(compiler
, sizeof(struct sljit_jump
));
2082 set_jump(jump
, compiler
, type
& SLJIT_REWRITABLE_JUMP
);
2085 if (type
<= SLJIT_NOT_EQUAL
) {
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)))) {
2095 if ((src1
& SLJIT_IMM
) && (src1w
== 0)) {
2098 case SLJIT_SIG_LESS
:
2100 jump
->flags
|= IS_BIT26_COND
;
2102 case SLJIT_SIG_GREATER_EQUAL
:
2104 jump
->flags
|= IS_BIT26_COND
;
2106 case SLJIT_SIG_GREATER
:
2108 jump
->flags
|= IS_BIT16_COND
;
2110 case SLJIT_SIG_LESS_EQUAL
:
2112 jump
->flags
|= IS_BIT16_COND
;
2120 case SLJIT_SIG_LESS
:
2122 jump
->flags
|= IS_BIT16_COND
;
2124 case SLJIT_SIG_GREATER_EQUAL
:
2126 jump
->flags
|= IS_BIT16_COND
;
2128 case SLJIT_SIG_GREATER
:
2130 jump
->flags
|= IS_BIT26_COND
;
2132 case SLJIT_SIG_LESS_EQUAL
:
2134 jump
->flags
|= IS_BIT26_COND
;
2138 PTR_FAIL_IF(push_inst(compiler
, inst
| S(src1
) | JUMP_LENGTH
, UNMOVABLE_INS
));
2141 if (type
== SLJIT_LESS
|| type
== SLJIT_GREATER_EQUAL
|| type
== SLJIT_SIG_LESS
|| type
== SLJIT_SIG_GREATER_EQUAL
) {
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
)));
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
;
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
)));
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
));
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
;
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
));
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));
2205 else if (src
& SLJIT_MEM
) {
2206 FAIL_IF(emit_op_mem(compiler
, WORD_DATA
| LOAD_DATA
, DR(TMP_REG2
), src
, srcw
));
2210 FAIL_IF(push_inst(compiler
, JR
| S(src
), UNMOVABLE_INS
));
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
,
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
;
2226 sljit_s32 mem_type
= ((op
& SLJIT_32
) || op
== SLJIT_MOV32
) ? (INT_DATA
| SIGNED_DATA
) : WORD_DATA
;
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) {
2244 case SLJIT_NOT_EQUAL
:
2245 FAIL_IF(push_inst(compiler
, SLTIU
| SA(EQUAL_FLAG
) | TA(dst_ar
) | IMM(1), dst_ar
));
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
;
2254 FAIL_IF(push_inst(compiler
, SLTIU
| SA(OTHER_FLAG
) | TA(dst_ar
) | IMM(1), dst_ar
));
2256 type
^= 0x1; /* Flip type bit for the XORI below. */
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
));
2278 src_ar
= OTHER_FLAG
;
2283 FAIL_IF(push_inst(compiler
, XORI
| SA(src_ar
) | TA(dst_ar
) | IMM(1), 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
,
2309 sljit_s32 src
, sljit_sw srcw
)
2311 #if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 1 && SLJIT_MIPS_REV < 6)
2313 #endif /* SLJIT_MIPS_REV >= 1 && SLJIT_MIPS_REV < 6 */
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
;
2325 FAIL_IF(load_immediate(compiler
, DR(TMP_REG1
), srcw
));
2330 dst_reg
&= ~SLJIT_32
;
2332 switch (type
& 0xff) {
2334 ins
= MOVZ
| TA(EQUAL_FLAG
);
2336 case SLJIT_NOT_EQUAL
:
2337 ins
= MOVN
| TA(EQUAL_FLAG
);
2341 case SLJIT_SIG_LESS
:
2342 case SLJIT_SIG_GREATER
:
2343 case SLJIT_OVERFLOW
:
2344 ins
= MOVN
| TA(OTHER_FLAG
);
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
);
2353 case SLJIT_EQUAL_F64
:
2354 case SLJIT_LESS_F64
:
2355 case SLJIT_LESS_EQUAL_F64
:
2356 case SLJIT_UNORDERED_F64
:
2359 case SLJIT_NOT_EQUAL_F64
:
2360 case SLJIT_GREATER_EQUAL_F64
:
2361 case SLJIT_GREATER_F64
:
2362 case SLJIT_ORDERED_F64
:
2366 ins
= MOVZ
| TA(OTHER_FLAG
);
2367 SLJIT_UNREACHABLE();
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_
;
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));
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
;
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));
2417 PTR_FAIL_IF(push_inst(compiler
, (sljit_ins
)dst_r
, UNMOVABLE_INS
));
2418 compiler
->size
+= 5;
2421 if (dst
& SLJIT_MEM
)
2422 PTR_FAIL_IF(emit_op(compiler
, SLJIT_MOV
, WORD_DATA
, dst
, dstw
, TMP_REG1
, 0, TMP_REG2
, 0));