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 SLJIT_API_FUNC_ATTRIBUTE
const char* sljit_get_platform_name(void)
29 #if (defined SLJIT_CONFIG_RISCV_32 && SLJIT_CONFIG_RISCV_32)
30 return "RISC-V-32" SLJIT_CPUINFO
;
31 #else /* !SLJIT_CONFIG_RISCV_32 */
32 return "RISC-V-64" SLJIT_CPUINFO
;
33 #endif /* SLJIT_CONFIG_RISCV_32 */
36 /* Length of an instruction word
37 Both for riscv-32 and riscv-64 */
38 typedef sljit_u32 sljit_ins
;
40 #define TMP_REG1 (SLJIT_NUMBER_OF_REGISTERS + 2)
41 #define TMP_REG2 (SLJIT_NUMBER_OF_REGISTERS + 3)
42 #define TMP_REG3 (SLJIT_NUMBER_OF_REGISTERS + 4)
45 /* Flags are kept in volatile registers. */
46 #define EQUAL_FLAG (SLJIT_NUMBER_OF_REGISTERS + 5)
47 #define RETURN_ADDR_REG TMP_REG2
48 #define OTHER_FLAG (SLJIT_NUMBER_OF_REGISTERS + 6)
50 #define TMP_FREG1 (SLJIT_NUMBER_OF_FLOAT_REGISTERS + 1)
51 #define TMP_FREG2 (SLJIT_NUMBER_OF_FLOAT_REGISTERS + 2)
53 static const sljit_u8 reg_map
[SLJIT_NUMBER_OF_REGISTERS
+ 7] = {
54 0, 10, 11, 12, 13, 14, 15, 16, 17, 29, 30, 31, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 9, 8, 2, 6, 1, 7, 5, 28
57 static const sljit_u8 freg_map
[SLJIT_NUMBER_OF_FLOAT_REGISTERS
+ 3] = {
58 0, 10, 11, 12, 13, 14, 15, 16, 17, 2, 3, 4, 5, 6, 7, 28, 29, 30, 31, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 9, 8, 0, 1,
61 /* --------------------------------------------------------------------- */
62 /* Instrucion forms */
63 /* --------------------------------------------------------------------- */
65 #define RD(rd) ((sljit_ins)reg_map[rd] << 7)
66 #define RS1(rs1) ((sljit_ins)reg_map[rs1] << 15)
67 #define RS2(rs2) ((sljit_ins)reg_map[rs2] << 20)
68 #define FRD(rd) ((sljit_ins)freg_map[rd] << 7)
69 #define FRS1(rs1) ((sljit_ins)freg_map[rs1] << 15)
70 #define FRS2(rs2) ((sljit_ins)freg_map[rs2] << 20)
71 #define IMM_I(imm) ((sljit_ins)(imm) << 20)
72 #define IMM_S(imm) ((((sljit_ins)(imm) & 0xfe0) << 20) | (((sljit_ins)(imm) & 0x1f) << 7))
74 /* Represents funct(i) parts of the instructions. */
75 #define OPC(o) ((sljit_ins)(o))
76 #define F3(f) ((sljit_ins)(f) << 12)
77 #define F12(f) ((sljit_ins)(f) << 20)
78 #define F7(f) ((sljit_ins)(f) << 25)
80 #define ADD (F7(0x0) | F3(0x0) | OPC(0x33))
81 #define ADDI (F3(0x0) | OPC(0x13))
82 #define AND (F7(0x0) | F3(0x7) | OPC(0x33))
83 #define ANDI (F3(0x7) | OPC(0x13))
84 #define AUIPC (OPC(0x17))
85 #define BEQ (F3(0x0) | OPC(0x63))
86 #define BNE (F3(0x1) | OPC(0x63))
87 #define BLT (F3(0x4) | OPC(0x63))
88 #define BGE (F3(0x5) | OPC(0x63))
89 #define BLTU (F3(0x6) | OPC(0x63))
90 #define BGEU (F3(0x7) | OPC(0x63))
91 #define DIV (F7(0x1) | F3(0x4) | OPC(0x33))
92 #define DIVU (F7(0x1) | F3(0x5) | OPC(0x33))
93 #define EBREAK (F12(0x1) | F3(0x0) | OPC(0x73))
94 #define FADD_S (F7(0x0) | F3(0x7) | OPC(0x53))
95 #define FDIV_S (F7(0xc) | F3(0x7) | OPC(0x53))
96 #define FEQ_S (F7(0x50) | F3(0x2) | OPC(0x53))
97 #define FLD (F3(0x3) | OPC(0x7))
98 #define FLE_S (F7(0x50) | F3(0x0) | OPC(0x53))
99 #define FLT_S (F7(0x50) | F3(0x1) | OPC(0x53))
100 #define FSD (F3(0x3) | OPC(0x27))
101 /* These conversion opcodes are partly defined. */
102 #define FCVT_S_D (F7(0x20) | OPC(0x53))
103 #define FCVT_S_W (F7(0x68) | OPC(0x53))
104 #define FCVT_W_S (F7(0x60) | F3(0x1) | OPC(0x53))
105 #define FMUL_S (F7(0x8) | F3(0x7) | OPC(0x53))
106 #define FSGNJ_S (F7(0x10) | F3(0x0) | OPC(0x53))
107 #define FSGNJN_S (F7(0x10) | F3(0x1) | OPC(0x53))
108 #define FSGNJX_S (F7(0x10) | F3(0x2) | OPC(0x53))
109 #define FSUB_S (F7(0x4) | F3(0x7) | OPC(0x53))
110 #define JAL (OPC(0x6f))
111 #define JALR (F3(0x0) | OPC(0x67))
112 #define LD (F3(0x3) | OPC(0x3))
113 #define LUI (OPC(0x37))
114 #define LW (F3(0x2) | OPC(0x3))
115 #define MUL (F7(0x1) | F3(0x0) | OPC(0x33))
116 #define MULH (F7(0x1) | F3(0x1) | OPC(0x33))
117 #define MULHU (F7(0x1) | F3(0x3) | OPC(0x33))
118 #define OR (F7(0x0) | F3(0x6) | OPC(0x33))
119 #define ORI (F3(0x6) | OPC(0x13))
120 #define REM (F7(0x1) | F3(0x6) | OPC(0x33))
121 #define REMU (F7(0x1) | F3(0x7) | OPC(0x33))
122 #define SD (F3(0x3) | OPC(0x23))
123 #define SLL (F7(0x0) | F3(0x1) | OPC(0x33))
124 #define SLLI (IMM_I(0x0) | F3(0x1) | OPC(0x13))
125 #define SLT (F7(0x0) | F3(0x2) | OPC(0x33))
126 #define SLTI (F3(0x2) | OPC(0x13))
127 #define SLTU (F7(0x0) | F3(0x3) | OPC(0x33))
128 #define SLTUI (F3(0x3) | OPC(0x13))
129 #define SRL (F7(0x0) | F3(0x5) | OPC(0x33))
130 #define SRLI (IMM_I(0x0) | F3(0x5) | OPC(0x13))
131 #define SRA (F7(0x20) | F3(0x5) | OPC(0x33))
132 #define SRAI (IMM_I(0x400) | F3(0x5) | OPC(0x13))
133 #define SUB (F7(0x20) | F3(0x0) | OPC(0x33))
134 #define SW (F3(0x2) | OPC(0x23))
135 #define XOR (F7(0x0) | F3(0x4) | OPC(0x33))
136 #define XORI (F3(0x4) | OPC(0x13))
138 #define SIMM_MAX (0x7ff)
139 #define SIMM_MIN (-0x800)
140 #define BRANCH_MAX (0xfff)
141 #define BRANCH_MIN (-0x1000)
142 #define JUMP_MAX (0xfffff)
143 #define JUMP_MIN (-0x100000)
145 #if (defined SLJIT_CONFIG_RISCV_64 && SLJIT_CONFIG_RISCV_64)
146 #define S32_MAX (0x7ffff7ffl)
147 #define S32_MIN (-0x80000000l)
148 #define S44_MAX (0x7fffffff7ffl)
149 #define S52_MAX (0x7ffffffffffffl)
152 static sljit_s32
push_inst(struct sljit_compiler
*compiler
, sljit_ins ins
)
154 sljit_ins
*ptr
= (sljit_ins
*)ensure_buf(compiler
, sizeof(sljit_ins
));
158 return SLJIT_SUCCESS
;
161 static sljit_s32
push_imm_s_inst(struct sljit_compiler
*compiler
, sljit_ins ins
, sljit_sw imm
)
163 return push_inst(compiler
, ins
| IMM_S(imm
));
166 static SLJIT_INLINE sljit_ins
* detect_jump_type(struct sljit_jump
*jump
, sljit_ins
*code
, sljit_sw executable_offset
)
169 sljit_uw target_addr
;
172 inst
= (sljit_ins
*)jump
->addr
;
174 if (jump
->flags
& SLJIT_REWRITABLE_JUMP
)
177 if (jump
->flags
& JUMP_ADDR
)
178 target_addr
= jump
->u
.target
;
180 SLJIT_ASSERT(jump
->flags
& JUMP_LABEL
);
181 target_addr
= (sljit_uw
)(code
+ jump
->u
.label
->size
) + (sljit_uw
)executable_offset
;
184 diff
= (sljit_sw
)target_addr
- (sljit_sw
)inst
- executable_offset
;
186 if (jump
->flags
& IS_COND
) {
188 diff
+= SSIZE_OF(ins
);
190 if (diff
>= BRANCH_MIN
&& diff
<= BRANCH_MAX
) {
191 jump
->flags
|= PATCH_B
;
192 inst
[0] = (inst
[0] & 0x1fff07f) ^ 0x1000;
193 jump
->addr
= (sljit_uw
)inst
;
198 diff
-= SSIZE_OF(ins
);
201 if (diff
>= JUMP_MIN
&& diff
<= JUMP_MAX
) {
202 if (jump
->flags
& IS_COND
) {
203 #if (defined SLJIT_CONFIG_RISCV_32 && SLJIT_CONFIG_RISCV_32)
204 inst
[-1] -= (sljit_ins
)(1 * sizeof(sljit_ins
)) << 7;
206 inst
[-1] -= (sljit_ins
)(5 * sizeof(sljit_ins
)) << 7;
210 jump
->flags
|= PATCH_J
;
214 #if (defined SLJIT_CONFIG_RISCV_64 && SLJIT_CONFIG_RISCV_64)
215 if (diff
>= S32_MIN
&& diff
<= S32_MAX
) {
216 if (jump
->flags
& IS_COND
)
217 inst
[-1] -= (sljit_ins
)(4 * sizeof(sljit_ins
)) << 7;
219 jump
->flags
|= PATCH_REL32
;
224 if (target_addr
<= (sljit_uw
)S32_MAX
) {
225 if (jump
->flags
& IS_COND
)
226 inst
[-1] -= (sljit_ins
)(4 * sizeof(sljit_ins
)) << 7;
228 jump
->flags
|= PATCH_ABS32
;
233 if (target_addr
<= S44_MAX
) {
234 if (jump
->flags
& IS_COND
)
235 inst
[-1] -= (sljit_ins
)(2 * sizeof(sljit_ins
)) << 7;
237 jump
->flags
|= PATCH_ABS44
;
242 if (target_addr
<= S52_MAX
) {
243 if (jump
->flags
& IS_COND
)
244 inst
[-1] -= (sljit_ins
)(1 * sizeof(sljit_ins
)) << 7;
246 jump
->flags
|= PATCH_ABS52
;
253 #if (defined SLJIT_CONFIG_RISCV_32 && SLJIT_CONFIG_RISCV_32)
262 #if (defined SLJIT_CONFIG_RISCV_64 && SLJIT_CONFIG_RISCV_64)
264 static SLJIT_INLINE sljit_sw
put_label_get_length(struct sljit_put_label
*put_label
, sljit_uw max_label
)
266 if (max_label
<= (sljit_uw
)S32_MAX
) {
267 put_label
->flags
= PATCH_ABS32
;
271 if (max_label
<= S44_MAX
) {
272 put_label
->flags
= PATCH_ABS44
;
276 if (max_label
<= S52_MAX
) {
277 put_label
->flags
= PATCH_ABS52
;
281 put_label
->flags
= 0;
285 #endif /* SLJIT_CONFIG_RISCV_64 */
287 static SLJIT_INLINE
void load_addr_to_reg(void *dst
, sljit_u32 reg
)
289 struct sljit_jump
*jump
= NULL
;
290 struct sljit_put_label
*put_label
;
293 #if (defined SLJIT_CONFIG_RISCV_64 && SLJIT_CONFIG_RISCV_64)
299 jump
= (struct sljit_jump
*)dst
;
301 inst
= (sljit_ins
*)jump
->addr
;
302 addr
= (flags
& JUMP_LABEL
) ? jump
->u
.label
->addr
: jump
->u
.target
;
304 put_label
= (struct sljit_put_label
*)dst
;
305 #if (defined SLJIT_CONFIG_RISCV_64 && SLJIT_CONFIG_RISCV_64)
306 flags
= put_label
->flags
;
308 inst
= (sljit_ins
*)put_label
->addr
;
309 addr
= put_label
->label
->addr
;
313 if ((addr
& 0x800) != 0)
316 #if (defined SLJIT_CONFIG_RISCV_32 && SLJIT_CONFIG_RISCV_32)
317 inst
[0] = LUI
| RD(reg
) | (sljit_ins
)((sljit_sw
)addr
& ~0xfff);
318 #else /* !SLJIT_CONFIG_RISCV_32 */
320 if (flags
& PATCH_ABS32
) {
321 SLJIT_ASSERT(addr
<= S32_MAX
);
322 inst
[0] = LUI
| RD(reg
) | (sljit_ins
)((sljit_sw
)addr
& ~0xfff);
323 } else if (flags
& PATCH_ABS44
) {
324 high
= (sljit_sw
)addr
>> 12;
325 SLJIT_ASSERT((sljit_uw
)high
<= 0x7fffffff);
327 if (high
> S32_MAX
) {
328 SLJIT_ASSERT((high
& 0x800) != 0);
329 inst
[0] = LUI
| RD(reg
) | (sljit_ins
)0x80000000u
;
330 inst
[1] = XORI
| RD(reg
) | RS1(reg
) | IMM_I(high
);
332 if ((high
& 0x800) != 0)
335 inst
[0] = LUI
| RD(reg
) | (sljit_ins
)(high
& ~0xfff);
336 inst
[1] = ADDI
| RD(reg
) | RS1(reg
) | IMM_I(high
);
339 inst
[2] = SLLI
| RD(reg
) | RS1(reg
) | IMM_I(12);
342 high
= (sljit_sw
)addr
>> 32;
344 if ((addr
& 0x80000000l
) != 0)
347 if ((high
& 0x800) != 0)
350 if (flags
& PATCH_ABS52
) {
351 SLJIT_ASSERT(addr
<= S52_MAX
);
352 inst
[0] = LUI
| RD(TMP_REG3
) | (sljit_ins
)(high
<< 12);
354 inst
[0] = LUI
| RD(TMP_REG3
) | (sljit_ins
)(high
& ~0xfff);
355 inst
[1] = ADDI
| RD(TMP_REG3
) | RS1(TMP_REG3
) | IMM_I(high
);
359 inst
[1] = LUI
| RD(reg
) | (sljit_ins
)((sljit_sw
)addr
& ~0xfff);
360 inst
[2] = SLLI
| RD(TMP_REG3
) | RS1(TMP_REG3
) | IMM_I((flags
& PATCH_ABS52
) ? 20 : 32);
361 inst
[3] = XOR
| RD(reg
) | RS1(reg
) | RS2(TMP_REG3
);
364 #endif /* !SLJIT_CONFIG_RISCV_32 */
367 SLJIT_ASSERT((inst
[1] & 0x707f) == JALR
);
368 inst
[1] = (inst
[1] & 0xfffff) | IMM_I(addr
);
370 inst
[1] = ADDI
| RD(reg
) | RS1(reg
) | IMM_I(addr
);
373 SLJIT_API_FUNC_ATTRIBUTE
void* sljit_generate_code(struct sljit_compiler
*compiler
)
375 struct sljit_memory_fragment
*buf
;
382 sljit_sw executable_offset
;
385 struct sljit_label
*label
;
386 struct sljit_jump
*jump
;
387 struct sljit_const
*const_
;
388 struct sljit_put_label
*put_label
;
391 CHECK_PTR(check_sljit_generate_code(compiler
));
392 reverse_buf(compiler
);
394 code
= (sljit_ins
*)SLJIT_MALLOC_EXEC(compiler
->size
* sizeof(sljit_ins
), compiler
->exec_allocator_data
);
395 PTR_FAIL_WITH_EXEC_IF(code
);
401 executable_offset
= SLJIT_EXEC_OFFSET(code
);
403 label
= compiler
->labels
;
404 jump
= compiler
->jumps
;
405 const_
= compiler
->consts
;
406 put_label
= compiler
->put_labels
;
409 buf_ptr
= (sljit_ins
*)buf
->memory
;
410 buf_end
= buf_ptr
+ (buf
->used_size
>> 2);
412 *code_ptr
= *buf_ptr
++;
413 if (next_addr
== word_count
) {
414 SLJIT_ASSERT(!label
|| label
->size
>= word_count
);
415 SLJIT_ASSERT(!jump
|| jump
->addr
>= word_count
);
416 SLJIT_ASSERT(!const_
|| const_
->addr
>= word_count
);
417 SLJIT_ASSERT(!put_label
|| put_label
->addr
>= word_count
);
419 /* These structures are ordered by their address. */
420 if (label
&& label
->size
== word_count
) {
421 label
->addr
= (sljit_uw
)SLJIT_ADD_EXEC_OFFSET(code_ptr
, executable_offset
);
422 label
->size
= (sljit_uw
)(code_ptr
- code
);
425 if (jump
&& jump
->addr
== word_count
) {
426 #if (defined SLJIT_CONFIG_RISCV_32 && SLJIT_CONFIG_RISCV_32)
431 jump
->addr
= (sljit_uw
)code_ptr
;
432 code_ptr
= detect_jump_type(jump
, code
, executable_offset
);
435 if (const_
&& const_
->addr
== word_count
) {
436 const_
->addr
= (sljit_uw
)code_ptr
;
437 const_
= const_
->next
;
439 if (put_label
&& put_label
->addr
== word_count
) {
440 SLJIT_ASSERT(put_label
->label
);
441 put_label
->addr
= (sljit_uw
)code_ptr
;
442 #if (defined SLJIT_CONFIG_RISCV_32 && SLJIT_CONFIG_RISCV_32)
446 code_ptr
+= put_label_get_length(put_label
, (sljit_uw
)(SLJIT_ADD_EXEC_OFFSET(code
, executable_offset
) + put_label
->label
->size
));
449 put_label
= put_label
->next
;
451 next_addr
= compute_next_addr(label
, jump
, const_
, put_label
);
455 } while (buf_ptr
< buf_end
);
460 if (label
&& label
->size
== word_count
) {
461 label
->addr
= (sljit_uw
)code_ptr
;
462 label
->size
= (sljit_uw
)(code_ptr
- code
);
466 SLJIT_ASSERT(!label
);
468 SLJIT_ASSERT(!const_
);
469 SLJIT_ASSERT(!put_label
);
470 SLJIT_ASSERT(code_ptr
- code
<= (sljit_sw
)compiler
->size
);
472 jump
= compiler
->jumps
;
475 if (!(jump
->flags
& (PATCH_B
| PATCH_J
| PATCH_REL32
))) {
476 load_addr_to_reg(jump
, TMP_REG1
);
480 addr
= (jump
->flags
& JUMP_LABEL
) ? jump
->u
.label
->addr
: jump
->u
.target
;
481 buf_ptr
= (sljit_ins
*)jump
->addr
;
482 addr
-= (sljit_uw
)SLJIT_ADD_EXEC_OFFSET(buf_ptr
, executable_offset
);
484 if (jump
->flags
& PATCH_B
) {
485 SLJIT_ASSERT((sljit_sw
)addr
>= BRANCH_MIN
&& (sljit_sw
)addr
<= BRANCH_MAX
);
486 addr
= ((addr
& 0x800) >> 4) | ((addr
& 0x1e) << 7) | ((addr
& 0x7e0) << 20) | ((addr
& 0x1000) << 19);
487 buf_ptr
[0] |= (sljit_ins
)addr
;
491 #if (defined SLJIT_CONFIG_RISCV_64 && SLJIT_CONFIG_RISCV_64)
492 if (jump
->flags
& PATCH_REL32
) {
493 SLJIT_ASSERT((sljit_sw
)addr
>= S32_MIN
&& (sljit_sw
)addr
<= S32_MAX
);
495 if ((addr
& 0x800) != 0)
498 buf_ptr
[0] = AUIPC
| RD(TMP_REG1
) | (sljit_ins
)((sljit_sw
)addr
& ~0xfff);
499 SLJIT_ASSERT((buf_ptr
[1] & 0x707f) == JALR
);
500 buf_ptr
[1] |= IMM_I(addr
);
505 SLJIT_ASSERT((sljit_sw
)addr
>= JUMP_MIN
&& (sljit_sw
)addr
<= JUMP_MAX
);
506 addr
= (addr
& 0xff000) | ((addr
& 0x800) << 9) | ((addr
& 0x7fe) << 20) | ((addr
& 0x100000) << 11);
507 buf_ptr
[0] = JAL
| RD((jump
->flags
& IS_CALL
) ? RETURN_ADDR_REG
: TMP_ZERO
) | (sljit_ins
)addr
;
512 put_label
= compiler
->put_labels
;
514 load_addr_to_reg(put_label
, 0);
515 put_label
= put_label
->next
;
518 compiler
->error
= SLJIT_ERR_COMPILED
;
519 compiler
->executable_offset
= executable_offset
;
520 compiler
->executable_size
= (sljit_uw
)(code_ptr
- code
) * sizeof(sljit_ins
);
522 code
= (sljit_ins
*)SLJIT_ADD_EXEC_OFFSET(code
, executable_offset
);
523 code_ptr
= (sljit_ins
*)SLJIT_ADD_EXEC_OFFSET(code_ptr
, executable_offset
);
525 SLJIT_CACHE_FLUSH(code
, code_ptr
);
526 SLJIT_UPDATE_WX_FLAGS(code
, code_ptr
, 1);
530 SLJIT_API_FUNC_ATTRIBUTE sljit_s32
sljit_has_cpu_feature(sljit_s32 feature_type
)
532 switch (feature_type
) {
534 case SLJIT_HAS_ZERO_REGISTER
:
541 SLJIT_API_FUNC_ATTRIBUTE sljit_s32
sljit_cmp_info(sljit_s32 type
)
543 return (type
>= SLJIT_ORDERED_EQUAL
&& type
<= SLJIT_ORDERED_LESS_EQUAL
);
546 /* --------------------------------------------------------------------- */
548 /* --------------------------------------------------------------------- */
550 /* Creates an index in data_transfer_insts array. */
551 #define LOAD_DATA 0x01
552 #define WORD_DATA 0x00
553 #define BYTE_DATA 0x02
554 #define HALF_DATA 0x04
555 #define INT_DATA 0x06
556 #define SIGNED_DATA 0x08
557 /* Separates integer and floating point registers */
559 #define DOUBLE_DATA 0x10
560 #define SINGLE_DATA 0x12
562 #define MEM_MASK 0x1f
564 #define ARG_TEST 0x00020
565 #define ALT_KEEP_CACHE 0x00040
566 #define CUMULATIVE_OP 0x00080
567 #define IMM_OP 0x00100
568 #define MOVE_OP 0x00200
569 #define SRC2_IMM 0x00400
571 #define UNUSED_DEST 0x00800
572 #define REG_DEST 0x01000
573 #define REG1_SOURCE 0x02000
574 #define REG2_SOURCE 0x04000
575 #define SLOW_SRC1 0x08000
576 #define SLOW_SRC2 0x10000
577 #define SLOW_DEST 0x20000
579 #if (defined SLJIT_CONFIG_RISCV_32 && SLJIT_CONFIG_RISCV_32)
580 #define STACK_STORE SW
581 #define STACK_LOAD LW
583 #define STACK_STORE SD
584 #define STACK_LOAD LD
587 #if (defined SLJIT_CONFIG_RISCV_32 && SLJIT_CONFIG_RISCV_32)
588 #include "sljitNativeRISCV_32.c"
590 #include "sljitNativeRISCV_64.c"
593 #define STACK_MAX_DISTANCE (-SIMM_MIN)
595 SLJIT_API_FUNC_ATTRIBUTE sljit_s32
sljit_emit_enter(struct sljit_compiler
*compiler
,
596 sljit_s32 options
, sljit_s32 arg_types
, sljit_s32 scratches
, sljit_s32 saveds
,
597 sljit_s32 fscratches
, sljit_s32 fsaveds
, sljit_s32 local_size
)
599 sljit_s32 i
, tmp
, offset
;
600 sljit_s32 saved_arg_count
= SLJIT_KEPT_SAVEDS_COUNT(options
);
603 CHECK(check_sljit_emit_enter(compiler
, options
, arg_types
, scratches
, saveds
, fscratches
, fsaveds
, local_size
));
604 set_emit_enter(compiler
, options
, arg_types
, scratches
, saveds
, fscratches
, fsaveds
, local_size
);
606 local_size
+= GET_SAVED_REGISTERS_SIZE(scratches
, saveds
- saved_arg_count
, 1);
607 #if (defined SLJIT_CONFIG_RISCV_32 && SLJIT_CONFIG_RISCV_32)
608 if (fsaveds
> 0 || fscratches
>= SLJIT_FIRST_SAVED_FLOAT_REG
) {
609 if ((local_size
& SSIZE_OF(sw
)) != 0)
610 local_size
+= SSIZE_OF(sw
);
611 local_size
+= GET_SAVED_FLOAT_REGISTERS_SIZE(fscratches
, fsaveds
, sizeof(sljit_f64
));
614 local_size
+= GET_SAVED_FLOAT_REGISTERS_SIZE(fscratches
, fsaveds
, sizeof(sljit_f64
));
616 local_size
= (local_size
+ SLJIT_LOCALS_OFFSET
+ 15) & ~0xf;
617 compiler
->local_size
= local_size
;
619 if (local_size
<= STACK_MAX_DISTANCE
) {
621 FAIL_IF(push_inst(compiler
, ADDI
| RD(SLJIT_SP
) | RS1(SLJIT_SP
) | IMM_I(-local_size
)));
622 offset
= local_size
- SSIZE_OF(sw
);
625 FAIL_IF(push_inst(compiler
, ADDI
| RD(SLJIT_SP
) | RS1(SLJIT_SP
) | IMM_I(STACK_MAX_DISTANCE
)));
626 local_size
-= STACK_MAX_DISTANCE
;
628 if (local_size
> STACK_MAX_DISTANCE
)
629 FAIL_IF(load_immediate(compiler
, TMP_REG1
, local_size
, TMP_REG3
));
630 offset
= STACK_MAX_DISTANCE
- SSIZE_OF(sw
);
633 FAIL_IF(push_imm_s_inst(compiler
, STACK_STORE
| RS1(SLJIT_SP
) | RS2(RETURN_ADDR_REG
), offset
));
635 tmp
= SLJIT_S0
- saveds
;
636 for (i
= SLJIT_S0
- saved_arg_count
; i
> tmp
; i
--) {
637 offset
-= SSIZE_OF(sw
);
638 FAIL_IF(push_imm_s_inst(compiler
, STACK_STORE
| RS1(SLJIT_SP
) | RS2(i
), offset
));
641 for (i
= scratches
; i
>= SLJIT_FIRST_SAVED_REG
; i
--) {
642 offset
-= SSIZE_OF(sw
);
643 FAIL_IF(push_imm_s_inst(compiler
, STACK_STORE
| RS1(SLJIT_SP
) | RS2(i
), offset
));
646 #if (defined SLJIT_CONFIG_RISCV_32 && SLJIT_CONFIG_RISCV_32)
647 /* This alignment is valid because offset is not used after storing FPU regs. */
648 if ((offset
& SSIZE_OF(sw
)) != 0)
649 offset
-= SSIZE_OF(sw
);
652 tmp
= SLJIT_FS0
- fsaveds
;
653 for (i
= SLJIT_FS0
; i
> tmp
; i
--) {
654 offset
-= SSIZE_OF(f64
);
655 FAIL_IF(push_imm_s_inst(compiler
, FSD
| RS1(SLJIT_SP
) | FRS2(i
), offset
));
658 for (i
= fscratches
; i
>= SLJIT_FIRST_SAVED_FLOAT_REG
; i
--) {
659 offset
-= SSIZE_OF(f64
);
660 FAIL_IF(push_imm_s_inst(compiler
, FSD
| RS1(SLJIT_SP
) | FRS2(i
), offset
));
663 if (local_size
> STACK_MAX_DISTANCE
)
664 FAIL_IF(push_inst(compiler
, SUB
| RD(SLJIT_SP
) | RS1(SLJIT_SP
) | RS2(TMP_REG1
)));
665 else if (local_size
> 0)
666 FAIL_IF(push_inst(compiler
, ADDI
| RD(SLJIT_SP
) | RS1(SLJIT_SP
) | IMM_I(-local_size
)));
668 if (options
& SLJIT_ENTER_REG_ARG
)
669 return SLJIT_SUCCESS
;
671 arg_types
>>= SLJIT_ARG_SHIFT
;
675 while (arg_types
> 0) {
676 if ((arg_types
& SLJIT_ARG_MASK
) < SLJIT_ARG_TYPE_F64
) {
677 if (!(arg_types
& SLJIT_ARG_TYPE_SCRATCH_REG
)) {
678 FAIL_IF(push_inst(compiler
, ADDI
| RD(SLJIT_S0
- saved_arg_count
) | RS1(tmp
) | IMM_I(0)));
684 arg_types
>>= SLJIT_ARG_SHIFT
;
687 return SLJIT_SUCCESS
;
690 #undef STACK_MAX_DISTANCE
692 SLJIT_API_FUNC_ATTRIBUTE sljit_s32
sljit_set_context(struct sljit_compiler
*compiler
,
693 sljit_s32 options
, sljit_s32 arg_types
, sljit_s32 scratches
, sljit_s32 saveds
,
694 sljit_s32 fscratches
, sljit_s32 fsaveds
, sljit_s32 local_size
)
697 CHECK(check_sljit_set_context(compiler
, options
, arg_types
, scratches
, saveds
, fscratches
, fsaveds
, local_size
));
698 set_set_context(compiler
, options
, arg_types
, scratches
, saveds
, fscratches
, fsaveds
, local_size
);
700 local_size
+= GET_SAVED_REGISTERS_SIZE(scratches
, saveds
- SLJIT_KEPT_SAVEDS_COUNT(options
), 1);
701 #if (defined SLJIT_CONFIG_RISCV_32 && SLJIT_CONFIG_RISCV_32)
702 if (fsaveds
> 0 || fscratches
>= SLJIT_FIRST_SAVED_FLOAT_REG
) {
703 if ((local_size
& SSIZE_OF(sw
)) != 0)
704 local_size
+= SSIZE_OF(sw
);
705 local_size
+= GET_SAVED_FLOAT_REGISTERS_SIZE(fscratches
, fsaveds
, sizeof(sljit_f64
));
708 local_size
+= GET_SAVED_FLOAT_REGISTERS_SIZE(fscratches
, fsaveds
, sizeof(sljit_f64
));
710 compiler
->local_size
= (local_size
+ SLJIT_LOCALS_OFFSET
+ 15) & ~0xf;
712 return SLJIT_SUCCESS
;
715 #define STACK_MAX_DISTANCE (-SIMM_MIN - 16)
717 static sljit_s32
emit_stack_frame_release(struct sljit_compiler
*compiler
)
719 sljit_s32 i
, tmp
, offset
;
720 sljit_s32 local_size
= compiler
->local_size
;
722 if (local_size
> STACK_MAX_DISTANCE
) {
723 local_size
-= STACK_MAX_DISTANCE
;
725 if (local_size
> STACK_MAX_DISTANCE
) {
726 FAIL_IF(load_immediate(compiler
, TMP_REG2
, local_size
, TMP_REG3
));
727 FAIL_IF(push_inst(compiler
, ADD
| RD(SLJIT_SP
) | RS1(SLJIT_SP
) | RS2(TMP_REG2
)));
729 FAIL_IF(push_inst(compiler
, ADDI
| RD(SLJIT_SP
) | RS1(SLJIT_SP
) | IMM_I(local_size
)));
731 local_size
= STACK_MAX_DISTANCE
;
734 SLJIT_ASSERT(local_size
> 0);
736 offset
= local_size
- SSIZE_OF(sw
);
737 FAIL_IF(push_inst(compiler
, STACK_LOAD
| RD(RETURN_ADDR_REG
) | RS1(SLJIT_SP
) | IMM_I(offset
)));
739 tmp
= SLJIT_S0
- compiler
->saveds
;
740 for (i
= SLJIT_S0
- SLJIT_KEPT_SAVEDS_COUNT(compiler
->options
); i
> tmp
; i
--) {
741 offset
-= SSIZE_OF(sw
);
742 FAIL_IF(push_inst(compiler
, STACK_LOAD
| RD(i
) | RS1(SLJIT_SP
) | IMM_I(offset
)));
745 for (i
= compiler
->scratches
; i
>= SLJIT_FIRST_SAVED_REG
; i
--) {
746 offset
-= SSIZE_OF(sw
);
747 FAIL_IF(push_inst(compiler
, STACK_LOAD
| RD(i
) | RS1(SLJIT_SP
) | IMM_I(offset
)));
750 #if (defined SLJIT_CONFIG_RISCV_32 && SLJIT_CONFIG_RISCV_32)
751 /* This alignment is valid because offset is not used after storing FPU regs. */
752 if ((offset
& SSIZE_OF(sw
)) != 0)
753 offset
-= SSIZE_OF(sw
);
756 tmp
= SLJIT_FS0
- compiler
->fsaveds
;
757 for (i
= SLJIT_FS0
; i
> tmp
; i
--) {
758 offset
-= SSIZE_OF(f64
);
759 FAIL_IF(push_inst(compiler
, FLD
| FRD(i
) | RS1(SLJIT_SP
) | IMM_I(offset
)));
762 for (i
= compiler
->fscratches
; i
>= SLJIT_FIRST_SAVED_FLOAT_REG
; i
--) {
763 offset
-= SSIZE_OF(f64
);
764 FAIL_IF(push_inst(compiler
, FLD
| FRD(i
) | RS1(SLJIT_SP
) | IMM_I(offset
)));
767 return push_inst(compiler
, ADDI
| RD(SLJIT_SP
) | RS1(SLJIT_SP
) | IMM_I(local_size
));
770 #undef STACK_MAX_DISTANCE
772 SLJIT_API_FUNC_ATTRIBUTE sljit_s32
sljit_emit_return_void(struct sljit_compiler
*compiler
)
775 CHECK(check_sljit_emit_return_void(compiler
));
777 FAIL_IF(emit_stack_frame_release(compiler
));
778 return push_inst(compiler
, JALR
| RD(TMP_ZERO
) | RS1(RETURN_ADDR_REG
) | IMM_I(0));
781 /* --------------------------------------------------------------------- */
783 /* --------------------------------------------------------------------- */
785 #if (defined SLJIT_CONFIG_RISCV_32 && SLJIT_CONFIG_RISCV_32)
786 #define ARCH_32_64(a, b) a
788 #define ARCH_32_64(a, b) b
791 static const sljit_ins data_transfer_insts
[16 + 4] = {
792 /* u w s */ ARCH_32_64(F3(0x2) | OPC(0x23) /* sw */, F3(0x3) | OPC(0x23) /* sd */),
793 /* u w l */ ARCH_32_64(F3(0x2) | OPC(0x3) /* lw */, F3(0x3) | OPC(0x3) /* ld */),
794 /* u b s */ F3(0x0) | OPC(0x23) /* sb */,
795 /* u b l */ F3(0x4) | OPC(0x3) /* lbu */,
796 /* u h s */ F3(0x1) | OPC(0x23) /* sh */,
797 /* u h l */ F3(0x5) | OPC(0x3) /* lhu */,
798 /* u i s */ F3(0x2) | OPC(0x23) /* sw */,
799 /* u i l */ ARCH_32_64(F3(0x2) | OPC(0x3) /* lw */, F3(0x6) | OPC(0x3) /* lwu */),
801 /* s w s */ ARCH_32_64(F3(0x2) | OPC(0x23) /* sw */, F3(0x3) | OPC(0x23) /* sd */),
802 /* s w l */ ARCH_32_64(F3(0x2) | OPC(0x3) /* lw */, F3(0x3) | OPC(0x3) /* ld */),
803 /* s b s */ F3(0x0) | OPC(0x23) /* sb */,
804 /* s b l */ F3(0x0) | OPC(0x3) /* lb */,
805 /* s h s */ F3(0x1) | OPC(0x23) /* sh */,
806 /* s h l */ F3(0x1) | OPC(0x3) /* lh */,
807 /* s i s */ F3(0x2) | OPC(0x23) /* sw */,
808 /* s i l */ F3(0x2) | OPC(0x3) /* lw */,
810 /* d s */ F3(0x3) | OPC(0x27) /* fsd */,
811 /* d l */ F3(0x3) | OPC(0x7) /* fld */,
812 /* s s */ F3(0x2) | OPC(0x27) /* fsw */,
813 /* s l */ F3(0x2) | OPC(0x7) /* flw */,
818 static sljit_s32
push_mem_inst(struct sljit_compiler
*compiler
, sljit_s32 flags
, sljit_s32 reg
, sljit_s32 base
, sljit_sw offset
)
822 SLJIT_ASSERT(FAST_IS_REG(base
) && offset
<= 0xfff && offset
>= SIMM_MIN
);
824 ins
= data_transfer_insts
[flags
& MEM_MASK
] | RS1(base
);
825 if (flags
& LOAD_DATA
)
826 ins
|= ((flags
& MEM_MASK
) <= GPR_REG
? RD(reg
) : FRD(reg
)) | IMM_I(offset
);
828 ins
|= ((flags
& MEM_MASK
) <= GPR_REG
? RS2(reg
) : FRS2(reg
)) | IMM_S(offset
);
830 return push_inst(compiler
, ins
);
833 /* Can perform an operation using at most 1 instruction. */
834 static sljit_s32
getput_arg_fast(struct sljit_compiler
*compiler
, sljit_s32 flags
, sljit_s32 reg
, sljit_s32 arg
, sljit_sw argw
)
837 SLJIT_ASSERT(arg
& SLJIT_MEM
);
839 if (!(arg
& OFFS_REG_MASK
) && argw
<= SIMM_MAX
&& argw
>= SIMM_MIN
) {
840 /* Works for both absoulte and relative addresses. */
841 if (SLJIT_UNLIKELY(flags
& ARG_TEST
))
844 FAIL_IF(push_mem_inst(compiler
, flags
, reg
, arg
& REG_MASK
, argw
));
850 #define TO_ARGW_HI(argw) (((argw) & ~0xfff) + (((argw) & 0x800) ? 0x1000 : 0))
852 /* See getput_arg below.
853 Note: can_cache is called only for binary operators. */
854 static sljit_s32
can_cache(sljit_s32 arg
, sljit_sw argw
, sljit_s32 next_arg
, sljit_sw next_argw
)
856 SLJIT_ASSERT((arg
& SLJIT_MEM
) && (next_arg
& SLJIT_MEM
));
858 /* Simple operation except for updates. */
859 if (arg
& OFFS_REG_MASK
) {
862 if (argw
&& argw
== next_argw
&& (arg
== next_arg
|| (arg
& OFFS_REG_MASK
) == (next_arg
& OFFS_REG_MASK
)))
867 if (arg
== next_arg
) {
868 if (((next_argw
- argw
) <= SIMM_MAX
&& (next_argw
- argw
) >= SIMM_MIN
)
869 || TO_ARGW_HI(argw
) == TO_ARGW_HI(next_argw
))
877 /* Emit the necessary instructions. See can_cache above. */
878 static sljit_s32
getput_arg(struct sljit_compiler
*compiler
, sljit_s32 flags
, sljit_s32 reg
, sljit_s32 arg
, sljit_sw argw
, sljit_s32 next_arg
, sljit_sw next_argw
)
880 sljit_s32 base
= arg
& REG_MASK
;
881 sljit_s32 tmp_r
= TMP_REG1
;
882 sljit_sw offset
, argw_hi
;
884 SLJIT_ASSERT(arg
& SLJIT_MEM
);
885 if (!(next_arg
& SLJIT_MEM
)) {
890 /* Since tmp can be the same as base or offset registers,
891 * these might be unavailable after modifying tmp. */
892 if ((flags
& MEM_MASK
) <= GPR_REG
&& (flags
& LOAD_DATA
))
895 if (SLJIT_UNLIKELY(arg
& OFFS_REG_MASK
)) {
898 /* Using the cache. */
899 if (argw
== compiler
->cache_argw
) {
900 if (arg
== compiler
->cache_arg
)
901 return push_mem_inst(compiler
, flags
, reg
, TMP_REG3
, 0);
903 if ((SLJIT_MEM
| (arg
& OFFS_REG_MASK
)) == compiler
->cache_arg
) {
904 if (arg
== next_arg
&& argw
== (next_argw
& 0x3)) {
905 compiler
->cache_arg
= arg
;
906 compiler
->cache_argw
= argw
;
907 FAIL_IF(push_inst(compiler
, ADD
| RD(TMP_REG3
) | RS1(TMP_REG3
) | RS2(base
)));
908 return push_mem_inst(compiler
, flags
, reg
, TMP_REG3
, 0);
910 FAIL_IF(push_inst(compiler
, ADD
| RD(tmp_r
) | RS1(base
) | RS2(TMP_REG3
)));
911 return push_mem_inst(compiler
, flags
, reg
, tmp_r
, 0);
915 if (SLJIT_UNLIKELY(argw
)) {
916 compiler
->cache_arg
= SLJIT_MEM
| (arg
& OFFS_REG_MASK
);
917 compiler
->cache_argw
= argw
;
918 FAIL_IF(push_inst(compiler
, SLLI
| RD(TMP_REG3
) | RS1(OFFS_REG(arg
)) | IMM_I(argw
)));
921 if (arg
== next_arg
&& argw
== (next_argw
& 0x3)) {
922 compiler
->cache_arg
= arg
;
923 compiler
->cache_argw
= argw
;
924 FAIL_IF(push_inst(compiler
, ADD
| RD(TMP_REG3
) | RS1(base
) | RS2(!argw
? OFFS_REG(arg
) : TMP_REG3
)));
928 FAIL_IF(push_inst(compiler
, ADD
| RD(tmp_r
) | RS1(base
) | RS2(!argw
? OFFS_REG(arg
) : TMP_REG3
)));
929 return push_mem_inst(compiler
, flags
, reg
, tmp_r
, 0);
932 if (compiler
->cache_arg
== arg
&& argw
- compiler
->cache_argw
<= SIMM_MAX
&& argw
- compiler
->cache_argw
>= SIMM_MIN
)
933 return push_mem_inst(compiler
, flags
, reg
, TMP_REG3
, argw
- compiler
->cache_argw
);
935 if (compiler
->cache_arg
== SLJIT_MEM
&& (argw
- compiler
->cache_argw
<= SIMM_MAX
) && (argw
- compiler
->cache_argw
>= SIMM_MIN
)) {
936 offset
= argw
- compiler
->cache_argw
;
938 compiler
->cache_arg
= SLJIT_MEM
;
940 argw_hi
= TO_ARGW_HI(argw
);
942 if (next_arg
&& next_argw
- argw
<= SIMM_MAX
&& next_argw
- argw
>= SIMM_MIN
&& argw_hi
!= TO_ARGW_HI(next_argw
)) {
943 FAIL_IF(load_immediate(compiler
, TMP_REG3
, argw
, tmp_r
));
944 compiler
->cache_argw
= argw
;
947 FAIL_IF(load_immediate(compiler
, TMP_REG3
, argw_hi
, tmp_r
));
948 compiler
->cache_argw
= argw_hi
;
949 offset
= argw
& 0xfff;
955 return push_mem_inst(compiler
, flags
, reg
, TMP_REG3
, offset
);
957 if (arg
== next_arg
&& next_argw
- argw
<= SIMM_MAX
&& next_argw
- argw
>= SIMM_MIN
) {
958 compiler
->cache_arg
= arg
;
959 FAIL_IF(push_inst(compiler
, ADD
| RD(TMP_REG3
) | RS1(TMP_REG3
) | RS2(base
)));
960 return push_mem_inst(compiler
, flags
, reg
, TMP_REG3
, offset
);
963 FAIL_IF(push_inst(compiler
, ADD
| RD(tmp_r
) | RS1(TMP_REG3
) | RS2(base
)));
964 return push_mem_inst(compiler
, flags
, reg
, tmp_r
, offset
);
967 static sljit_s32
emit_op_mem(struct sljit_compiler
*compiler
, sljit_s32 flags
, sljit_s32 reg
, sljit_s32 arg
, sljit_sw argw
)
969 sljit_s32 base
= arg
& REG_MASK
;
970 sljit_s32 tmp_r
= TMP_REG1
;
972 if (getput_arg_fast(compiler
, flags
, reg
, arg
, argw
))
973 return compiler
->error
;
975 if ((flags
& MEM_MASK
) <= GPR_REG
&& (flags
& LOAD_DATA
))
978 if (SLJIT_UNLIKELY(arg
& OFFS_REG_MASK
)) {
981 if (SLJIT_UNLIKELY(argw
)) {
982 FAIL_IF(push_inst(compiler
, SLLI
| RD(tmp_r
) | RS1(OFFS_REG(arg
)) | IMM_I(argw
)));
983 FAIL_IF(push_inst(compiler
, ADD
| RD(tmp_r
) | RS1(base
) | RS2(tmp_r
)));
986 FAIL_IF(push_inst(compiler
, ADD
| RD(tmp_r
) | RS1(base
) | RS2(OFFS_REG(arg
))));
987 return push_mem_inst(compiler
, flags
, reg
, tmp_r
, 0);
990 FAIL_IF(load_immediate(compiler
, tmp_r
, TO_ARGW_HI(argw
), TMP_REG3
));
993 FAIL_IF(push_inst(compiler
, ADD
| RD(tmp_r
) | RS1(base
) | RS2(tmp_r
)));
995 return push_mem_inst(compiler
, flags
, reg
, tmp_r
, argw
& 0xfff);
1000 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
)
1002 if (getput_arg_fast(compiler
, flags
, reg
, arg1
, arg1w
))
1003 return compiler
->error
;
1004 return getput_arg(compiler
, flags
, reg
, arg1
, arg1w
, arg2
, arg2w
);
1007 #if (defined SLJIT_CONFIG_RISCV_32 && SLJIT_CONFIG_RISCV_32)
1009 #define IMM_EXTEND(v) (IMM_I(v))
1010 #else /* !SLJIT_CONFIG_RISCV_32 */
1012 #define IMM_EXTEND(v) (IMM_I((op & SLJIT_32) ? (v) : (32 + (v))))
1013 #endif /* SLJIT_CONFIG_RISCV_32 */
1015 #define EMIT_LOGICAL(op_imm, op_reg) \
1016 if (flags & SRC2_IMM) { \
1017 if (op & SLJIT_SET_Z) \
1018 FAIL_IF(push_inst(compiler, op_imm | RD(EQUAL_FLAG) | RS1(src1) | IMM_I(src2))); \
1019 if (!(flags & UNUSED_DEST)) \
1020 FAIL_IF(push_inst(compiler, op_imm | RD(dst) | RS1(src1) | IMM_I(src2))); \
1023 if (op & SLJIT_SET_Z) \
1024 FAIL_IF(push_inst(compiler, op_reg | RD(EQUAL_FLAG) | RS1(src1) | RS2(src2))); \
1025 if (!(flags & UNUSED_DEST)) \
1026 FAIL_IF(push_inst(compiler, op_reg | RD(dst) | RS1(src1) | RS2(src2))); \
1029 #define EMIT_SHIFT(op_imm, op_reg) \
1030 if (flags & SRC2_IMM) { \
1031 if (op & SLJIT_SET_Z) \
1032 FAIL_IF(push_inst(compiler, op_imm | WORD | RD(EQUAL_FLAG) | RS1(src1) | IMM_I(src2))); \
1033 if (!(flags & UNUSED_DEST)) \
1034 FAIL_IF(push_inst(compiler, op_imm | WORD | RD(dst) | RS1(src1) | IMM_I(src2))); \
1037 if (op & SLJIT_SET_Z) \
1038 FAIL_IF(push_inst(compiler, op_reg | WORD | RD(EQUAL_FLAG) | RS1(src1) | RS2(src2))); \
1039 if (!(flags & UNUSED_DEST)) \
1040 FAIL_IF(push_inst(compiler, op_reg | WORD | RD(dst) | RS1(src1) | RS2(src2))); \
1043 static SLJIT_INLINE sljit_s32
emit_single_op(struct sljit_compiler
*compiler
, sljit_s32 op
, sljit_s32 flags
,
1044 sljit_s32 dst
, sljit_s32 src1
, sljit_sw src2
)
1046 sljit_s32 is_overflow
, is_carry
, carry_src_r
, is_handled
;
1047 #if (defined SLJIT_CONFIG_RISCV_64 && SLJIT_CONFIG_RISCV_64)
1048 sljit_ins word
= (op
& SLJIT_32
) >> 5;
1050 SLJIT_ASSERT(word
== 0 || word
== 0x8);
1051 #endif /* SLJIT_CONFIG_RISCV_64 */
1053 switch (GET_OPCODE(op
)) {
1055 SLJIT_ASSERT(src1
== TMP_REG1
&& !(flags
& SRC2_IMM
));
1057 return push_inst(compiler
, ADDI
| RD(dst
) | RS1(src2
) | IMM_I(0));
1058 return SLJIT_SUCCESS
;
1061 SLJIT_ASSERT(src1
== TMP_REG1
&& !(flags
& SRC2_IMM
));
1062 if ((flags
& (REG_DEST
| REG2_SOURCE
)) == (REG_DEST
| REG2_SOURCE
))
1063 return push_inst(compiler
, ANDI
| RD(dst
) | RS1(src2
) | IMM_I(0xff));
1064 SLJIT_ASSERT(dst
== src2
);
1065 return SLJIT_SUCCESS
;
1068 SLJIT_ASSERT(src1
== TMP_REG1
&& !(flags
& SRC2_IMM
));
1069 if ((flags
& (REG_DEST
| REG2_SOURCE
)) == (REG_DEST
| REG2_SOURCE
)) {
1070 FAIL_IF(push_inst(compiler
, SLLI
| WORD
| RD(dst
) | RS1(src2
) | IMM_EXTEND(24)));
1071 return push_inst(compiler
, SRAI
| WORD
| RD(dst
) | RS1(dst
) | IMM_EXTEND(24));
1073 SLJIT_ASSERT(dst
== src2
);
1074 return SLJIT_SUCCESS
;
1077 SLJIT_ASSERT(src1
== TMP_REG1
&& !(flags
& SRC2_IMM
));
1078 if ((flags
& (REG_DEST
| REG2_SOURCE
)) == (REG_DEST
| REG2_SOURCE
)) {
1079 FAIL_IF(push_inst(compiler
, SLLI
| WORD
| RD(dst
) | RS1(src2
) | IMM_EXTEND(16)));
1080 return push_inst(compiler
, SRLI
| WORD
| RD(dst
) | RS1(dst
) | IMM_EXTEND(16));
1082 SLJIT_ASSERT(dst
== src2
);
1083 return SLJIT_SUCCESS
;
1086 SLJIT_ASSERT(src1
== TMP_REG1
&& !(flags
& SRC2_IMM
));
1087 if ((flags
& (REG_DEST
| REG2_SOURCE
)) == (REG_DEST
| REG2_SOURCE
)) {
1088 FAIL_IF(push_inst(compiler
, SLLI
| WORD
| RD(dst
) | RS1(src2
) | IMM_EXTEND(16)));
1089 return push_inst(compiler
, SRAI
| WORD
| RD(dst
) | RS1(dst
) | IMM_EXTEND(16));
1091 SLJIT_ASSERT(dst
== src2
);
1092 return SLJIT_SUCCESS
;
1094 #if (defined SLJIT_CONFIG_RISCV_64 && SLJIT_CONFIG_RISCV_64)
1096 SLJIT_ASSERT(src1
== TMP_REG1
&& !(flags
& SRC2_IMM
));
1097 if ((flags
& (REG_DEST
| REG2_SOURCE
)) == (REG_DEST
| REG2_SOURCE
)) {
1098 FAIL_IF(push_inst(compiler
, SLLI
| RD(dst
) | RS1(src2
) | IMM_I(32)));
1099 return push_inst(compiler
, SRLI
| RD(dst
) | RS1(dst
) | IMM_I(32));
1101 SLJIT_ASSERT(dst
== src2
);
1102 return SLJIT_SUCCESS
;
1105 SLJIT_ASSERT(src1
== TMP_REG1
&& !(flags
& SRC2_IMM
));
1106 if ((flags
& (REG_DEST
| REG2_SOURCE
)) == (REG_DEST
| REG2_SOURCE
))
1107 return push_inst(compiler
, ADDI
| 0x8 | RD(dst
) | RS1(src2
) | IMM_I(0));
1108 SLJIT_ASSERT(dst
== src2
);
1109 return SLJIT_SUCCESS
;
1110 #endif /* SLJIT_CONFIG_RISCV_64 */
1113 SLJIT_ASSERT(src1
== TMP_REG1
&& !(flags
& SRC2_IMM
));
1114 /* Nearly all instructions are unmovable in the following sequence. */
1115 #if (defined SLJIT_CONFIG_RISCV_32 && SLJIT_CONFIG_RISCV_32)
1116 FAIL_IF(push_inst(compiler
, ADDI
| RD(TMP_REG1
) | RS1(src2
) | IMM_I(0)));
1117 FAIL_IF(push_inst(compiler
, ADDI
| RD(dst
) | RS1(TMP_ZERO
) | IMM_I(32)));
1118 #else /* !SLJIT_CONFIG_RISCV_32 */
1119 if (op
& SLJIT_32
) {
1120 FAIL_IF(push_inst(compiler
, SLLI
| RD(TMP_REG1
) | RS1(src2
) | IMM_I(32)));
1121 FAIL_IF(push_inst(compiler
, ADDI
| RD(dst
) | RS1(TMP_ZERO
) | IMM_I(32)));
1123 FAIL_IF(push_inst(compiler
, ADDI
| RD(TMP_REG1
) | RS1(src2
) | IMM_I(0)));
1124 FAIL_IF(push_inst(compiler
, ADDI
| RD(dst
) | RS1(TMP_ZERO
) | IMM_I(64)));
1126 #endif /* SLJIT_CONFIG_RISCV_32 */
1128 FAIL_IF(push_inst(compiler
, BEQ
| RS1(TMP_REG1
) | RS2(TMP_ZERO
) | ((sljit_ins
)(6 * SSIZE_OF(ins
)) << 7)));
1129 FAIL_IF(push_inst(compiler
, ADDI
| RD(dst
) | RS1(TMP_ZERO
) | IMM_I(0)));
1130 FAIL_IF(push_inst(compiler
, BLT
| RS1(TMP_REG1
) | RS2(TMP_ZERO
) | ((sljit_ins
)(4 * SSIZE_OF(ins
)) << 7)));
1131 /* Loop for searching the highest bit. */
1132 FAIL_IF(push_inst(compiler
, ADDI
| RD(dst
) | RS1(dst
) | IMM_I(1)));
1133 FAIL_IF(push_inst(compiler
, SLLI
| RD(TMP_REG1
) | RS1(TMP_REG1
) | IMM_I(1)));
1134 FAIL_IF(push_inst(compiler
, BGE
| RS1(TMP_REG1
) | RS2(TMP_ZERO
) | ((sljit_ins
)(0x1fc001d - 1 * SSIZE_OF(ins
)) << 7)));
1135 return SLJIT_SUCCESS
;
1138 /* Overflow computation (both add and sub): overflow = src1_sign ^ src2_sign ^ result_sign ^ carry_flag */
1139 is_overflow
= GET_FLAG_TYPE(op
) == SLJIT_OVERFLOW
;
1140 carry_src_r
= GET_FLAG_TYPE(op
) == GET_FLAG_TYPE(SLJIT_SET_CARRY
);
1142 if (flags
& SRC2_IMM
) {
1145 FAIL_IF(push_inst(compiler
, ADDI
| RD(EQUAL_FLAG
) | RS1(src1
) | IMM_I(0)));
1147 FAIL_IF(push_inst(compiler
, XORI
| RD(EQUAL_FLAG
) | RS1(src1
) | IMM_I(-1)));
1149 else if (op
& SLJIT_SET_Z
)
1150 FAIL_IF(push_inst(compiler
, ADDI
| WORD
| RD(EQUAL_FLAG
) | RS1(src1
) | IMM_I(src2
)));
1152 /* Only the zero flag is needed. */
1153 if (!(flags
& UNUSED_DEST
) || (op
& VARIABLE_FLAG_MASK
))
1154 FAIL_IF(push_inst(compiler
, ADDI
| WORD
| RD(dst
) | RS1(src1
) | IMM_I(src2
)));
1158 FAIL_IF(push_inst(compiler
, XOR
| RD(EQUAL_FLAG
) | RS1(src1
) | RS2(src2
)));
1159 else if (op
& SLJIT_SET_Z
)
1160 FAIL_IF(push_inst(compiler
, ADD
| WORD
| RD(EQUAL_FLAG
) | RS1(src1
) | RS2(src2
)));
1162 if (is_overflow
|| carry_src_r
!= 0) {
1164 carry_src_r
= (sljit_s32
)src1
;
1165 else if (src2
!= dst
)
1166 carry_src_r
= (sljit_s32
)src2
;
1168 FAIL_IF(push_inst(compiler
, ADDI
| RD(OTHER_FLAG
) | RS1(src1
) | IMM_I(0)));
1169 carry_src_r
= OTHER_FLAG
;
1173 /* Only the zero flag is needed. */
1174 if (!(flags
& UNUSED_DEST
) || (op
& VARIABLE_FLAG_MASK
))
1175 FAIL_IF(push_inst(compiler
, ADD
| WORD
| RD(dst
) | RS1(src1
) | RS2(src2
)));
1178 /* Carry is zero if a + b >= a or a + b >= b, otherwise it is 1. */
1179 if (is_overflow
|| carry_src_r
!= 0) {
1180 if (flags
& SRC2_IMM
)
1181 FAIL_IF(push_inst(compiler
, SLTUI
| RD(OTHER_FLAG
) | RS1(dst
) | IMM_I(src2
)));
1183 FAIL_IF(push_inst(compiler
, SLTU
| RD(OTHER_FLAG
) | RS1(dst
) | RS2(carry_src_r
)));
1187 return SLJIT_SUCCESS
;
1189 FAIL_IF(push_inst(compiler
, XOR
| RD(TMP_REG1
) | RS1(dst
) | RS2(EQUAL_FLAG
)));
1190 if (op
& SLJIT_SET_Z
)
1191 FAIL_IF(push_inst(compiler
, ADDI
| RD(EQUAL_FLAG
) | RS1(dst
) | IMM_I(0)));
1192 FAIL_IF(push_inst(compiler
, SRLI
| WORD
| RD(TMP_REG1
) | RS1(TMP_REG1
) | IMM_EXTEND(31)));
1193 return push_inst(compiler
, XOR
| RD(OTHER_FLAG
) | RS1(TMP_REG1
) | RS2(OTHER_FLAG
));
1196 carry_src_r
= GET_FLAG_TYPE(op
) == GET_FLAG_TYPE(SLJIT_SET_CARRY
);
1198 if (flags
& SRC2_IMM
) {
1199 FAIL_IF(push_inst(compiler
, ADDI
| WORD
| RD(dst
) | RS1(src1
) | IMM_I(src2
)));
1201 if (carry_src_r
!= 0) {
1203 carry_src_r
= (sljit_s32
)src1
;
1204 else if (src2
!= dst
)
1205 carry_src_r
= (sljit_s32
)src2
;
1207 FAIL_IF(push_inst(compiler
, ADDI
| RD(EQUAL_FLAG
) | RS1(src1
) | IMM_I(0)));
1208 carry_src_r
= EQUAL_FLAG
;
1212 FAIL_IF(push_inst(compiler
, ADD
| WORD
| RD(dst
) | RS1(src1
) | RS2(src2
)));
1215 /* Carry is zero if a + b >= a or a + b >= b, otherwise it is 1. */
1216 if (carry_src_r
!= 0) {
1217 if (flags
& SRC2_IMM
)
1218 FAIL_IF(push_inst(compiler
, SLTUI
| RD(EQUAL_FLAG
) | RS1(dst
) | IMM_I(src2
)));
1220 FAIL_IF(push_inst(compiler
, SLTU
| RD(EQUAL_FLAG
) | RS1(dst
) | RS2(carry_src_r
)));
1223 FAIL_IF(push_inst(compiler
, ADD
| WORD
| RD(dst
) | RS1(dst
) | RS2(OTHER_FLAG
)));
1225 if (carry_src_r
== 0)
1226 return SLJIT_SUCCESS
;
1228 /* Set ULESS_FLAG (dst == 0) && (OTHER_FLAG == 1). */
1229 FAIL_IF(push_inst(compiler
, SLTU
| RD(OTHER_FLAG
) | RS1(dst
) | RS2(OTHER_FLAG
)));
1230 /* Set carry flag. */
1231 return push_inst(compiler
, OR
| RD(OTHER_FLAG
) | RS1(OTHER_FLAG
) | RS2(EQUAL_FLAG
));
1234 if ((flags
& SRC2_IMM
) && src2
== SIMM_MIN
) {
1235 FAIL_IF(push_inst(compiler
, ADDI
| RD(TMP_REG2
) | RS1(TMP_ZERO
) | IMM_I(src2
)));
1242 if (flags
& SRC2_IMM
) {
1243 if (GET_FLAG_TYPE(op
) == SLJIT_LESS
|| GET_FLAG_TYPE(op
) == SLJIT_GREATER_EQUAL
) {
1244 FAIL_IF(push_inst(compiler
, SLTUI
| RD(OTHER_FLAG
) | RS1(src1
) | IMM_I(src2
)));
1247 else if (GET_FLAG_TYPE(op
) == SLJIT_SIG_LESS
|| GET_FLAG_TYPE(op
) == SLJIT_SIG_GREATER_EQUAL
) {
1248 FAIL_IF(push_inst(compiler
, SLTI
| RD(OTHER_FLAG
) | RS1(src1
) | IMM_I(src2
)));
1253 if (!is_handled
&& GET_FLAG_TYPE(op
) >= SLJIT_LESS
&& GET_FLAG_TYPE(op
) <= SLJIT_SIG_LESS_EQUAL
) {
1256 if (flags
& SRC2_IMM
) {
1257 FAIL_IF(push_inst(compiler
, ADDI
| RD(TMP_REG2
) | RS1(TMP_ZERO
) | IMM_I(src2
)));
1262 switch (GET_FLAG_TYPE(op
)) {
1264 case SLJIT_GREATER_EQUAL
:
1265 FAIL_IF(push_inst(compiler
, SLTU
| RD(OTHER_FLAG
) | RS1(src1
) | RS2(src2
)));
1268 case SLJIT_LESS_EQUAL
:
1269 FAIL_IF(push_inst(compiler
, SLTU
| RD(OTHER_FLAG
) | RS1(src2
) | RS2(src1
)));
1271 case SLJIT_SIG_LESS
:
1272 case SLJIT_SIG_GREATER_EQUAL
:
1273 FAIL_IF(push_inst(compiler
, SLT
| RD(OTHER_FLAG
) | RS1(src1
) | RS2(src2
)));
1275 case SLJIT_SIG_GREATER
:
1276 case SLJIT_SIG_LESS_EQUAL
:
1277 FAIL_IF(push_inst(compiler
, SLT
| RD(OTHER_FLAG
) | RS1(src2
) | RS2(src1
)));
1283 if (flags
& SRC2_IMM
) {
1284 if (op
& SLJIT_SET_Z
)
1285 FAIL_IF(push_inst(compiler
, ADDI
| WORD
| RD(EQUAL_FLAG
) | RS1(src1
) | IMM_I(-src2
)));
1286 if (!(flags
& UNUSED_DEST
))
1287 return push_inst(compiler
, ADDI
| WORD
| RD(dst
) | RS1(src1
) | IMM_I(-src2
));
1290 if (op
& SLJIT_SET_Z
)
1291 FAIL_IF(push_inst(compiler
, SUB
| WORD
| RD(EQUAL_FLAG
) | RS1(src1
) | RS2(src2
)));
1292 if (!(flags
& UNUSED_DEST
))
1293 return push_inst(compiler
, SUB
| WORD
| RD(dst
) | RS1(src1
) | RS2(src2
));
1295 return SLJIT_SUCCESS
;
1298 is_overflow
= GET_FLAG_TYPE(op
) == SLJIT_OVERFLOW
;
1299 is_carry
= GET_FLAG_TYPE(op
) == GET_FLAG_TYPE(SLJIT_SET_CARRY
);
1301 if (flags
& SRC2_IMM
) {
1304 FAIL_IF(push_inst(compiler
, ADDI
| RD(EQUAL_FLAG
) | RS1(src1
) | IMM_I(0)));
1306 FAIL_IF(push_inst(compiler
, XORI
| RD(EQUAL_FLAG
) | RS1(src1
) | IMM_I(-1)));
1308 else if (op
& SLJIT_SET_Z
)
1309 FAIL_IF(push_inst(compiler
, ADDI
| WORD
| RD(EQUAL_FLAG
) | RS1(src1
) | IMM_I(-src2
)));
1311 if (is_overflow
|| is_carry
)
1312 FAIL_IF(push_inst(compiler
, SLTUI
| RD(OTHER_FLAG
) | RS1(src1
) | IMM_I(src2
)));
1314 /* Only the zero flag is needed. */
1315 if (!(flags
& UNUSED_DEST
) || (op
& VARIABLE_FLAG_MASK
))
1316 FAIL_IF(push_inst(compiler
, ADDI
| WORD
| RD(dst
) | RS1(src1
) | IMM_I(-src2
)));
1320 FAIL_IF(push_inst(compiler
, XOR
| RD(EQUAL_FLAG
) | RS1(src1
) | RS2(src2
)));
1321 else if (op
& SLJIT_SET_Z
)
1322 FAIL_IF(push_inst(compiler
, SUB
| WORD
| RD(EQUAL_FLAG
) | RS1(src1
) | RS2(src2
)));
1324 if (is_overflow
|| is_carry
)
1325 FAIL_IF(push_inst(compiler
, SLTU
| RD(OTHER_FLAG
) | RS1(src1
) | RS2(src2
)));
1327 /* Only the zero flag is needed. */
1328 if (!(flags
& UNUSED_DEST
) || (op
& VARIABLE_FLAG_MASK
))
1329 FAIL_IF(push_inst(compiler
, SUB
| WORD
| RD(dst
) | RS1(src1
) | RS2(src2
)));
1333 return SLJIT_SUCCESS
;
1335 FAIL_IF(push_inst(compiler
, XOR
| RD(TMP_REG1
) | RS1(dst
) | RS2(EQUAL_FLAG
)));
1336 if (op
& SLJIT_SET_Z
)
1337 FAIL_IF(push_inst(compiler
, ADDI
| RD(EQUAL_FLAG
) | RS1(dst
) | IMM_I(0)));
1338 FAIL_IF(push_inst(compiler
, SRLI
| WORD
| RD(TMP_REG1
) | RS1(TMP_REG1
) | IMM_EXTEND(31)));
1339 return push_inst(compiler
, XOR
| RD(OTHER_FLAG
) | RS1(TMP_REG1
) | RS2(OTHER_FLAG
));
1342 if ((flags
& SRC2_IMM
) && src2
== SIMM_MIN
) {
1343 FAIL_IF(push_inst(compiler
, ADDI
| RD(TMP_REG2
) | RS1(TMP_ZERO
) | IMM_I(src2
)));
1348 is_carry
= GET_FLAG_TYPE(op
) == GET_FLAG_TYPE(SLJIT_SET_CARRY
);
1350 if (flags
& SRC2_IMM
) {
1352 FAIL_IF(push_inst(compiler
, SLTUI
| RD(EQUAL_FLAG
) | RS1(src1
) | IMM_I(src2
)));
1354 FAIL_IF(push_inst(compiler
, ADDI
| WORD
| RD(dst
) | RS1(src1
) | IMM_I(-src2
)));
1358 FAIL_IF(push_inst(compiler
, SLTU
| RD(EQUAL_FLAG
) | RS1(src1
) | RS2(src2
)));
1360 FAIL_IF(push_inst(compiler
, SUB
| WORD
| RD(dst
) | RS1(src1
) | RS2(src2
)));
1364 FAIL_IF(push_inst(compiler
, SLTU
| RD(TMP_REG1
) | RS1(dst
) | RS2(OTHER_FLAG
)));
1366 FAIL_IF(push_inst(compiler
, SUB
| WORD
| RD(dst
) | RS1(dst
) | RS2(OTHER_FLAG
)));
1369 return SLJIT_SUCCESS
;
1371 return push_inst(compiler
, OR
| RD(OTHER_FLAG
) | RS1(EQUAL_FLAG
) | RS2(TMP_REG1
));
1374 SLJIT_ASSERT(!(flags
& SRC2_IMM
));
1376 if (GET_FLAG_TYPE(op
) != SLJIT_OVERFLOW
)
1377 return push_inst(compiler
, MUL
| WORD
| RD(dst
) | RS1(src1
) | RS2(src2
));
1379 #if (defined SLJIT_CONFIG_RISCV_64 && SLJIT_CONFIG_RISCV_64)
1381 FAIL_IF(push_inst(compiler
, MUL
| RD(OTHER_FLAG
) | RS1(src1
) | RS2(src2
)));
1382 FAIL_IF(push_inst(compiler
, MUL
| 0x8 | RD(dst
) | RS1(src1
) | RS2(src2
)));
1383 return push_inst(compiler
, SUB
| RD(OTHER_FLAG
) | RS1(dst
) | RS2(OTHER_FLAG
));
1385 #endif /* SLJIT_CONFIG_RISCV_64 */
1387 FAIL_IF(push_inst(compiler
, MULH
| RD(EQUAL_FLAG
) | RS1(src1
) | RS2(src2
)));
1388 FAIL_IF(push_inst(compiler
, MUL
| RD(dst
) | RS1(src1
) | RS2(src2
)));
1389 #if (defined SLJIT_CONFIG_RISCV_32 && SLJIT_CONFIG_RISCV_32)
1390 FAIL_IF(push_inst(compiler
, SRAI
| RD(OTHER_FLAG
) | RS1(dst
) | IMM_I(31)));
1391 #else /* !SLJIT_CONFIG_RISCV_32 */
1392 FAIL_IF(push_inst(compiler
, SRAI
| RD(OTHER_FLAG
) | RS1(dst
) | IMM_I(63)));
1393 #endif /* SLJIT_CONFIG_RISCV_32 */
1394 return push_inst(compiler
, SUB
| RD(OTHER_FLAG
) | RS1(EQUAL_FLAG
) | RS2(OTHER_FLAG
));
1397 EMIT_LOGICAL(ANDI
, AND
);
1398 return SLJIT_SUCCESS
;
1401 EMIT_LOGICAL(ORI
, OR
);
1402 return SLJIT_SUCCESS
;
1405 EMIT_LOGICAL(XORI
, XOR
);
1406 return SLJIT_SUCCESS
;
1409 EMIT_SHIFT(SLLI
, SLL
);
1410 return SLJIT_SUCCESS
;
1413 EMIT_SHIFT(SRLI
, SRL
);
1414 return SLJIT_SUCCESS
;
1417 EMIT_SHIFT(SRAI
, SRA
);
1418 return SLJIT_SUCCESS
;
1421 SLJIT_UNREACHABLE();
1422 return SLJIT_SUCCESS
;
1427 static sljit_s32
emit_op(struct sljit_compiler
*compiler
, sljit_s32 op
, sljit_s32 flags
,
1428 sljit_s32 dst
, sljit_sw dstw
,
1429 sljit_s32 src1
, sljit_sw src1w
,
1430 sljit_s32 src2
, sljit_sw src2w
)
1432 /* arg1 goes to TMP_REG1 or src reg
1433 arg2 goes to TMP_REG2, imm or src reg
1434 TMP_REG3 can be used for caching
1435 result goes to TMP_REG2, so put result can use TMP_REG1 and TMP_REG3. */
1436 sljit_s32 dst_r
= TMP_REG2
;
1438 sljit_sw src2_r
= 0;
1439 sljit_s32 sugg_src2_r
= TMP_REG2
;
1441 if (!(flags
& ALT_KEEP_CACHE
)) {
1442 compiler
->cache_arg
= 0;
1443 compiler
->cache_argw
= 0;
1446 if (dst
== TMP_REG2
) {
1447 SLJIT_ASSERT(HAS_FLAGS(op
));
1448 flags
|= UNUSED_DEST
;
1450 else if (FAST_IS_REG(dst
)) {
1453 if (flags
& MOVE_OP
)
1454 sugg_src2_r
= dst_r
;
1456 else if ((dst
& SLJIT_MEM
) && !getput_arg_fast(compiler
, flags
| ARG_TEST
, TMP_REG1
, dst
, dstw
))
1459 if (flags
& IMM_OP
) {
1460 if ((src2
& SLJIT_IMM
) && src2w
!= 0 && src2w
<= SIMM_MAX
&& src2w
>= SIMM_MIN
) {
1464 else if ((flags
& CUMULATIVE_OP
) && (src1
& SLJIT_IMM
) && src1w
!= 0 && src1w
<= SIMM_MAX
&& src1w
>= SIMM_MIN
) {
1468 /* And swap arguments. */
1472 /* src2w = src2_r unneeded. */
1477 if (FAST_IS_REG(src1
)) {
1479 flags
|= REG1_SOURCE
;
1481 else if (src1
& SLJIT_IMM
) {
1483 FAIL_IF(load_immediate(compiler
, TMP_REG1
, src1w
, TMP_REG3
));
1490 if (getput_arg_fast(compiler
, flags
| LOAD_DATA
, TMP_REG1
, src1
, src1w
))
1491 FAIL_IF(compiler
->error
);
1498 if (FAST_IS_REG(src2
)) {
1500 flags
|= REG2_SOURCE
;
1501 if ((flags
& (REG_DEST
| MOVE_OP
)) == MOVE_OP
)
1502 dst_r
= (sljit_s32
)src2_r
;
1504 else if (src2
& SLJIT_IMM
) {
1505 if (!(flags
& SRC2_IMM
)) {
1507 FAIL_IF(load_immediate(compiler
, sugg_src2_r
, src2w
, TMP_REG3
));
1508 src2_r
= sugg_src2_r
;
1512 if (flags
& MOVE_OP
) {
1513 if (dst
& SLJIT_MEM
)
1522 if (getput_arg_fast(compiler
, flags
| LOAD_DATA
, sugg_src2_r
, src2
, src2w
))
1523 FAIL_IF(compiler
->error
);
1526 src2_r
= sugg_src2_r
;
1529 if ((flags
& (SLOW_SRC1
| SLOW_SRC2
)) == (SLOW_SRC1
| SLOW_SRC2
)) {
1530 SLJIT_ASSERT(src2_r
== TMP_REG2
);
1531 if (!can_cache(src1
, src1w
, src2
, src2w
) && can_cache(src1
, src1w
, dst
, dstw
)) {
1532 FAIL_IF(getput_arg(compiler
, flags
| LOAD_DATA
, TMP_REG2
, src2
, src2w
, src1
, src1w
));
1533 FAIL_IF(getput_arg(compiler
, flags
| LOAD_DATA
, TMP_REG1
, src1
, src1w
, dst
, dstw
));
1536 FAIL_IF(getput_arg(compiler
, flags
| LOAD_DATA
, TMP_REG1
, src1
, src1w
, src2
, src2w
));
1537 FAIL_IF(getput_arg(compiler
, flags
| LOAD_DATA
, TMP_REG2
, src2
, src2w
, dst
, dstw
));
1540 else if (flags
& SLOW_SRC1
)
1541 FAIL_IF(getput_arg(compiler
, flags
| LOAD_DATA
, TMP_REG1
, src1
, src1w
, dst
, dstw
));
1542 else if (flags
& SLOW_SRC2
)
1543 FAIL_IF(getput_arg(compiler
, flags
| LOAD_DATA
, sugg_src2_r
, src2
, src2w
, dst
, dstw
));
1545 FAIL_IF(emit_single_op(compiler
, op
, flags
, dst_r
, src1_r
, src2_r
));
1547 if (dst
& SLJIT_MEM
) {
1548 if (!(flags
& SLOW_DEST
)) {
1549 getput_arg_fast(compiler
, flags
, dst_r
, dst
, dstw
);
1550 return compiler
->error
;
1552 return getput_arg(compiler
, flags
, dst_r
, dst
, dstw
, 0, 0);
1555 return SLJIT_SUCCESS
;
1558 SLJIT_API_FUNC_ATTRIBUTE sljit_s32
sljit_emit_op0(struct sljit_compiler
*compiler
, sljit_s32 op
)
1560 #if (defined SLJIT_CONFIG_RISCV_64 && SLJIT_CONFIG_RISCV_64)
1561 sljit_ins word
= (op
& SLJIT_32
) >> 5;
1563 SLJIT_ASSERT(word
== 0 || word
== 0x8);
1564 #endif /* SLJIT_CONFIG_RISCV_64 */
1567 CHECK(check_sljit_emit_op0(compiler
, op
));
1569 switch (GET_OPCODE(op
)) {
1570 case SLJIT_BREAKPOINT
:
1571 return push_inst(compiler
, EBREAK
);
1573 return push_inst(compiler
, ADDI
| RD(TMP_ZERO
) | RS1(TMP_ZERO
) | IMM_I(0));
1575 FAIL_IF(push_inst(compiler
, ADDI
| RD(TMP_REG1
) | RS1(SLJIT_R1
) | IMM_I(0)));
1576 FAIL_IF(push_inst(compiler
, MULHU
| RD(SLJIT_R1
) | RS1(SLJIT_R0
) | RS2(SLJIT_R1
)));
1577 return push_inst(compiler
, MUL
| RD(SLJIT_R0
) | RS1(SLJIT_R0
) | RS2(TMP_REG1
));
1579 FAIL_IF(push_inst(compiler
, ADDI
| RD(TMP_REG1
) | RS1(SLJIT_R1
) | IMM_I(0)));
1580 FAIL_IF(push_inst(compiler
, MULH
| RD(SLJIT_R1
) | RS1(SLJIT_R0
) | RS2(SLJIT_R1
)));
1581 return push_inst(compiler
, MUL
| RD(SLJIT_R0
) | RS1(SLJIT_R0
) | RS2(TMP_REG1
));
1582 case SLJIT_DIVMOD_UW
:
1583 FAIL_IF(push_inst(compiler
, ADDI
| RD(TMP_REG1
) | RS1(SLJIT_R0
) | IMM_I(0)));
1584 FAIL_IF(push_inst(compiler
, DIVU
| WORD
| RD(SLJIT_R0
) | RS1(SLJIT_R0
) | RS2(SLJIT_R1
)));
1585 return push_inst(compiler
, REMU
| WORD
| RD(SLJIT_R1
) | RS1(TMP_REG1
) | RS2(SLJIT_R1
));
1586 case SLJIT_DIVMOD_SW
:
1587 FAIL_IF(push_inst(compiler
, ADDI
| RD(TMP_REG1
) | RS1(SLJIT_R0
) | IMM_I(0)));
1588 FAIL_IF(push_inst(compiler
, DIV
| WORD
| RD(SLJIT_R0
) | RS1(SLJIT_R0
) | RS2(SLJIT_R1
)));
1589 return push_inst(compiler
, REM
| WORD
| RD(SLJIT_R1
) | RS1(TMP_REG1
) | RS2(SLJIT_R1
));
1591 return push_inst(compiler
, DIVU
| WORD
| RD(SLJIT_R0
) | RS1(SLJIT_R0
) | RS2(SLJIT_R1
));
1593 return push_inst(compiler
, DIV
| WORD
| RD(SLJIT_R0
) | RS1(SLJIT_R0
) | RS2(SLJIT_R1
));
1595 case SLJIT_SKIP_FRAMES_BEFORE_RETURN
:
1596 return SLJIT_SUCCESS
;
1599 return SLJIT_SUCCESS
;
1604 SLJIT_API_FUNC_ATTRIBUTE sljit_s32
sljit_emit_op1(struct sljit_compiler
*compiler
, sljit_s32 op
,
1605 sljit_s32 dst
, sljit_sw dstw
,
1606 sljit_s32 src
, sljit_sw srcw
)
1608 sljit_s32 flags
= 0;
1611 CHECK(check_sljit_emit_op1(compiler
, op
, dst
, dstw
, src
, srcw
));
1612 ADJUST_LOCAL_OFFSET(dst
, dstw
);
1613 ADJUST_LOCAL_OFFSET(src
, srcw
);
1615 #if (defined SLJIT_CONFIG_RISCV_64 && SLJIT_CONFIG_RISCV_64)
1617 flags
= INT_DATA
| SIGNED_DATA
;
1620 switch (GET_OPCODE(op
)) {
1622 #if (defined SLJIT_CONFIG_RISCV_32 && SLJIT_CONFIG_RISCV_32)
1628 return emit_op(compiler
, SLJIT_MOV
, WORD_DATA
| MOVE_OP
, dst
, dstw
, TMP_REG1
, 0, src
, srcw
);
1630 #if (defined SLJIT_CONFIG_RISCV_64 && SLJIT_CONFIG_RISCV_64)
1632 return emit_op(compiler
, SLJIT_MOV_U32
, INT_DATA
| MOVE_OP
, dst
, dstw
, TMP_REG1
, 0, src
, (src
& SLJIT_IMM
) ? (sljit_u32
)srcw
: srcw
);
1635 /* Logical operators have no W variant, so sign extended input is necessary for them. */
1637 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
);
1641 return emit_op(compiler
, op
, BYTE_DATA
| MOVE_OP
, dst
, dstw
, TMP_REG1
, 0, src
, (src
& SLJIT_IMM
) ? (sljit_u8
)srcw
: srcw
);
1644 return emit_op(compiler
, op
, BYTE_DATA
| SIGNED_DATA
| MOVE_OP
, dst
, dstw
, TMP_REG1
, 0, src
, (src
& SLJIT_IMM
) ? (sljit_s8
)srcw
: srcw
);
1647 return emit_op(compiler
, op
, HALF_DATA
| MOVE_OP
, dst
, dstw
, TMP_REG1
, 0, src
, (src
& SLJIT_IMM
) ? (sljit_u16
)srcw
: srcw
);
1650 return emit_op(compiler
, op
, HALF_DATA
| SIGNED_DATA
| MOVE_OP
, dst
, dstw
, TMP_REG1
, 0, src
, (src
& SLJIT_IMM
) ? (sljit_s16
)srcw
: srcw
);
1653 return emit_op(compiler
, SLJIT_XOR
| (op
& (SLJIT_32
| SLJIT_SET_Z
)), flags
, dst
, dstw
, src
, srcw
, SLJIT_IMM
, -1);
1656 return emit_op(compiler
, op
, flags
, dst
, dstw
, TMP_REG1
, 0, src
, srcw
);
1659 SLJIT_UNREACHABLE();
1660 return SLJIT_SUCCESS
;
1663 SLJIT_API_FUNC_ATTRIBUTE sljit_s32
sljit_emit_op2(struct sljit_compiler
*compiler
, sljit_s32 op
,
1664 sljit_s32 dst
, sljit_sw dstw
,
1665 sljit_s32 src1
, sljit_sw src1w
,
1666 sljit_s32 src2
, sljit_sw src2w
)
1668 sljit_s32 flags
= 0;
1671 CHECK(check_sljit_emit_op2(compiler
, op
, 0, dst
, dstw
, src1
, src1w
, src2
, src2w
));
1672 ADJUST_LOCAL_OFFSET(dst
, dstw
);
1673 ADJUST_LOCAL_OFFSET(src1
, src1w
);
1674 ADJUST_LOCAL_OFFSET(src2
, src2w
);
1676 #if (defined SLJIT_CONFIG_RISCV_64 && SLJIT_CONFIG_RISCV_64)
1677 if (op
& SLJIT_32
) {
1678 flags
|= INT_DATA
| SIGNED_DATA
;
1679 if (src1
& SLJIT_IMM
)
1680 src1w
= (sljit_s32
)src1w
;
1681 if (src2
& SLJIT_IMM
)
1682 src2w
= (sljit_s32
)src2w
;
1686 switch (GET_OPCODE(op
)) {
1689 compiler
->status_flags_state
= SLJIT_CURRENT_FLAGS_ADD
;
1690 return emit_op(compiler
, op
, flags
| CUMULATIVE_OP
| IMM_OP
, dst
, dstw
, src1
, src1w
, src2
, src2w
);
1694 compiler
->status_flags_state
= SLJIT_CURRENT_FLAGS_SUB
;
1695 return emit_op(compiler
, op
, flags
| IMM_OP
, dst
, dstw
, src1
, src1w
, src2
, src2w
);
1698 compiler
->status_flags_state
= 0;
1699 return emit_op(compiler
, op
, flags
| CUMULATIVE_OP
, dst
, dstw
, src1
, src1w
, src2
, src2w
);
1704 return emit_op(compiler
, op
, flags
| CUMULATIVE_OP
| IMM_OP
, dst
, dstw
, src1
, src1w
, src2
, src2w
);
1709 #if (defined SLJIT_CONFIG_RISCV_32 && SLJIT_CONFIG_RISCV_32)
1710 if (src2
& SLJIT_IMM
)
1713 if (src2
& SLJIT_IMM
) {
1720 return emit_op(compiler
, op
, flags
| IMM_OP
, dst
, dstw
, src1
, src1w
, src2
, src2w
);
1723 SLJIT_UNREACHABLE();
1724 return SLJIT_SUCCESS
;
1727 SLJIT_API_FUNC_ATTRIBUTE sljit_s32
sljit_emit_op2u(struct sljit_compiler
*compiler
, sljit_s32 op
,
1728 sljit_s32 src1
, sljit_sw src1w
,
1729 sljit_s32 src2
, sljit_sw src2w
)
1732 CHECK(check_sljit_emit_op2(compiler
, op
, 1, 0, 0, src1
, src1w
, src2
, src2w
));
1734 SLJIT_SKIP_CHECKS(compiler
);
1735 return sljit_emit_op2(compiler
, op
, TMP_REG2
, 0, src1
, src1w
, src2
, src2w
);
1738 SLJIT_API_FUNC_ATTRIBUTE sljit_s32
sljit_emit_op_src(struct sljit_compiler
*compiler
, sljit_s32 op
,
1739 sljit_s32 src
, sljit_sw srcw
)
1742 CHECK(check_sljit_emit_op_src(compiler
, op
, src
, srcw
));
1743 ADJUST_LOCAL_OFFSET(src
, srcw
);
1746 case SLJIT_FAST_RETURN
:
1747 if (FAST_IS_REG(src
))
1748 FAIL_IF(push_inst(compiler
, ADDI
| RD(RETURN_ADDR_REG
) | RS1(src
) | IMM_I(0)));
1750 FAIL_IF(emit_op_mem(compiler
, WORD_DATA
| LOAD_DATA
, RETURN_ADDR_REG
, src
, srcw
));
1752 return push_inst(compiler
, JALR
| RD(TMP_ZERO
) | RS1(RETURN_ADDR_REG
) | IMM_I(0));
1753 case SLJIT_SKIP_FRAMES_BEFORE_FAST_RETURN
:
1754 return SLJIT_SUCCESS
;
1755 case SLJIT_PREFETCH_L1
:
1756 case SLJIT_PREFETCH_L2
:
1757 case SLJIT_PREFETCH_L3
:
1758 case SLJIT_PREFETCH_ONCE
:
1759 return SLJIT_SUCCESS
;
1762 return SLJIT_SUCCESS
;
1765 SLJIT_API_FUNC_ATTRIBUTE sljit_s32
sljit_get_register_index(sljit_s32 reg
)
1767 CHECK_REG_INDEX(check_sljit_get_register_index(reg
));
1768 return reg_map
[reg
];
1771 SLJIT_API_FUNC_ATTRIBUTE sljit_s32
sljit_get_float_register_index(sljit_s32 reg
)
1773 CHECK_REG_INDEX(check_sljit_get_float_register_index(reg
));
1774 return freg_map
[reg
];
1777 SLJIT_API_FUNC_ATTRIBUTE sljit_s32
sljit_emit_op_custom(struct sljit_compiler
*compiler
,
1778 void *instruction
, sljit_u32 size
)
1781 CHECK(check_sljit_emit_op_custom(compiler
, instruction
, size
));
1783 return push_inst(compiler
, *(sljit_ins
*)instruction
);
1786 /* --------------------------------------------------------------------- */
1787 /* Floating point operators */
1788 /* --------------------------------------------------------------------- */
1790 #define FLOAT_DATA(op) (DOUBLE_DATA | ((op & SLJIT_32) >> 7))
1791 #define FMT(op) ((sljit_ins)((op & SLJIT_32) ^ SLJIT_32) << 17)
1793 static SLJIT_INLINE sljit_s32
sljit_emit_fop1_conv_sw_from_f64(struct sljit_compiler
*compiler
, sljit_s32 op
,
1794 sljit_s32 dst
, sljit_sw dstw
,
1795 sljit_s32 src
, sljit_sw srcw
)
1797 #if (defined SLJIT_CONFIG_RISCV_32 && SLJIT_CONFIG_RISCV_32)
1798 # define flags (sljit_u32)0
1800 sljit_u32 flags
= ((sljit_u32
)(GET_OPCODE(op
) == SLJIT_CONV_SW_FROM_F64
)) << 21;
1802 sljit_s32 dst_r
= FAST_IS_REG(dst
) ? dst
: TMP_REG2
;
1804 if (src
& SLJIT_MEM
) {
1805 FAIL_IF(emit_op_mem2(compiler
, FLOAT_DATA(op
) | LOAD_DATA
, TMP_FREG1
, src
, srcw
, dst
, dstw
));
1809 FAIL_IF(push_inst(compiler
, FCVT_W_S
| FMT(op
) | flags
| RD(dst_r
) | FRS1(src
)));
1811 /* Store the integer value from a VFP register. */
1812 if (dst
& SLJIT_MEM
) {
1813 #if (defined SLJIT_CONFIG_RISCV_32 && SLJIT_CONFIG_RISCV_32)
1814 return emit_op_mem2(compiler
, WORD_DATA
, TMP_REG2
, dst
, dstw
, 0, 0);
1816 return emit_op_mem2(compiler
, flags
? WORD_DATA
: INT_DATA
, TMP_REG2
, dst
, dstw
, 0, 0);
1819 return SLJIT_SUCCESS
;
1821 #if (defined SLJIT_CONFIG_RISCV_32 && SLJIT_CONFIG_RISCV_32)
1826 static SLJIT_INLINE sljit_s32
sljit_emit_fop1_conv_f64_from_sw(struct sljit_compiler
*compiler
, sljit_s32 op
,
1827 sljit_s32 dst
, sljit_sw dstw
,
1828 sljit_s32 src
, sljit_sw srcw
)
1831 #if (defined SLJIT_CONFIG_RISCV_64 && SLJIT_CONFIG_RISCV_64)
1832 sljit_u32 flags
= ((sljit_u32
)(GET_OPCODE(op
) == SLJIT_CONV_F64_FROM_SW
)) << 21;
1835 sljit_s32 dst_r
= FAST_IS_REG(dst
) ? dst
: TMP_FREG1
;
1837 if (src
& SLJIT_MEM
) {
1838 #if (defined SLJIT_CONFIG_RISCV_32 && SLJIT_CONFIG_RISCV_32)
1839 FAIL_IF(emit_op_mem2(compiler
, WORD_DATA
| LOAD_DATA
, TMP_REG1
, src
, srcw
, dst
, dstw
));
1841 FAIL_IF(emit_op_mem2(compiler
, (flags
? WORD_DATA
: INT_DATA
) | LOAD_DATA
, TMP_REG1
, src
, srcw
, dst
, dstw
));
1844 } else if (src
& SLJIT_IMM
) {
1845 #if (defined SLJIT_CONFIG_RISCV_64 && SLJIT_CONFIG_RISCV_64)
1846 if (GET_OPCODE(op
) == SLJIT_CONV_F64_FROM_S32
)
1847 srcw
= (sljit_s32
)srcw
;
1850 FAIL_IF(load_immediate(compiler
, TMP_REG1
, srcw
, TMP_REG3
));
1854 inst
= FCVT_S_W
| FMT(op
) | FRD(dst_r
) | RS1(src
);
1856 #if (defined SLJIT_CONFIG_RISCV_32 && SLJIT_CONFIG_RISCV_32)
1862 if (op
!= SLJIT_CONV_F64_FROM_S32
)
1866 FAIL_IF(push_inst(compiler
, inst
));
1868 if (dst
& SLJIT_MEM
)
1869 return emit_op_mem2(compiler
, FLOAT_DATA(op
), TMP_FREG1
, dst
, dstw
, 0, 0);
1870 return SLJIT_SUCCESS
;
1873 static SLJIT_INLINE sljit_s32
sljit_emit_fop1_cmp(struct sljit_compiler
*compiler
, sljit_s32 op
,
1874 sljit_s32 src1
, sljit_sw src1w
,
1875 sljit_s32 src2
, sljit_sw src2w
)
1879 if (src1
& SLJIT_MEM
) {
1880 FAIL_IF(emit_op_mem2(compiler
, FLOAT_DATA(op
) | LOAD_DATA
, TMP_FREG1
, src1
, src1w
, src2
, src2w
));
1884 if (src2
& SLJIT_MEM
) {
1885 FAIL_IF(emit_op_mem2(compiler
, FLOAT_DATA(op
) | LOAD_DATA
, TMP_FREG2
, src2
, src2w
, 0, 0));
1889 switch (GET_FLAG_TYPE(op
)) {
1891 case SLJIT_F_NOT_EQUAL
:
1892 case SLJIT_ORDERED_EQUAL
:
1893 case SLJIT_UNORDERED_OR_NOT_EQUAL
:
1894 inst
= FEQ_S
| FMT(op
) | RD(OTHER_FLAG
) | FRS1(src1
) | FRS2(src2
);
1897 case SLJIT_F_GREATER_EQUAL
:
1898 case SLJIT_ORDERED_LESS
:
1899 case SLJIT_UNORDERED_OR_GREATER_EQUAL
:
1900 inst
= FLT_S
| FMT(op
) | RD(OTHER_FLAG
) | FRS1(src1
) | FRS2(src2
);
1902 case SLJIT_ORDERED_GREATER
:
1903 case SLJIT_UNORDERED_OR_LESS_EQUAL
:
1904 inst
= FLT_S
| FMT(op
) | RD(OTHER_FLAG
) | FRS1(src2
) | FRS2(src1
);
1906 case SLJIT_F_GREATER
:
1907 case SLJIT_F_LESS_EQUAL
:
1908 case SLJIT_UNORDERED_OR_GREATER
:
1909 case SLJIT_ORDERED_LESS_EQUAL
:
1910 inst
= FLE_S
| FMT(op
) | RD(OTHER_FLAG
) | FRS1(src1
) | FRS2(src2
);
1912 case SLJIT_UNORDERED_OR_LESS
:
1913 case SLJIT_ORDERED_GREATER_EQUAL
:
1914 inst
= FLE_S
| FMT(op
) | RD(OTHER_FLAG
) | FRS1(src2
) | FRS2(src1
);
1916 case SLJIT_UNORDERED_OR_EQUAL
: /* Not supported. */
1917 case SLJIT_ORDERED_NOT_EQUAL
: /* Not supported. */
1918 FAIL_IF(push_inst(compiler
, FLT_S
| FMT(op
) | RD(OTHER_FLAG
) | FRS1(src1
) | FRS2(src2
)));
1919 FAIL_IF(push_inst(compiler
, FLT_S
| FMT(op
) | RD(TMP_REG1
) | FRS1(src2
) | FRS2(src1
)));
1920 inst
= OR
| RD(OTHER_FLAG
) | RS1(OTHER_FLAG
) | RS2(TMP_REG1
);
1922 default: /* SLJIT_UNORDERED, SLJIT_ORDERED */
1923 FAIL_IF(push_inst(compiler
, FADD_S
| FMT(op
) | FRD(TMP_FREG1
) | FRS1(src1
) | FRS2(src2
)));
1924 inst
= FEQ_S
| FMT(op
) | RD(OTHER_FLAG
) | FRS1(TMP_FREG1
) | FRS2(TMP_FREG1
);
1928 return push_inst(compiler
, inst
);
1931 SLJIT_API_FUNC_ATTRIBUTE sljit_s32
sljit_emit_fop1(struct sljit_compiler
*compiler
, sljit_s32 op
,
1932 sljit_s32 dst
, sljit_sw dstw
,
1933 sljit_s32 src
, sljit_sw srcw
)
1938 compiler
->cache_arg
= 0;
1939 compiler
->cache_argw
= 0;
1941 SLJIT_COMPILE_ASSERT((SLJIT_32
== 0x100) && !(DOUBLE_DATA
& 0x2), float_transfer_bit_error
);
1942 SELECT_FOP1_OPERATION_WITH_CHECKS(compiler
, op
, dst
, dstw
, src
, srcw
);
1944 if (GET_OPCODE(op
) == SLJIT_CONV_F64_FROM_F32
)
1947 dst_r
= FAST_IS_REG(dst
) ? dst
: TMP_FREG1
;
1949 if (src
& SLJIT_MEM
) {
1950 FAIL_IF(emit_op_mem2(compiler
, FLOAT_DATA(op
) | LOAD_DATA
, dst_r
, src
, srcw
, dst
, dstw
));
1954 switch (GET_OPCODE(op
)) {
1957 if (dst_r
!= TMP_FREG1
)
1958 FAIL_IF(push_inst(compiler
, FSGNJ_S
| FMT(op
) | FRD(dst_r
) | FRS1(src
) | FRS2(src
)));
1964 FAIL_IF(push_inst(compiler
, FSGNJN_S
| FMT(op
) | FRD(dst_r
) | FRS1(src
) | FRS2(src
)));
1967 FAIL_IF(push_inst(compiler
, FSGNJX_S
| FMT(op
) | FRD(dst_r
) | FRS1(src
) | FRS2(src
)));
1969 case SLJIT_CONV_F64_FROM_F32
:
1970 /* The SLJIT_32 bit is inverted because sljit_f32 needs to be loaded from the memory. */
1971 FAIL_IF(push_inst(compiler
, FCVT_S_D
| ((op
& SLJIT_32
) ? (1 << 25) : ((1 << 20) | F3(7))) | FRD(dst_r
) | FRS1(src
)));
1976 if (dst
& SLJIT_MEM
)
1977 return emit_op_mem2(compiler
, FLOAT_DATA(op
), dst_r
, dst
, dstw
, 0, 0);
1978 return SLJIT_SUCCESS
;
1981 SLJIT_API_FUNC_ATTRIBUTE sljit_s32
sljit_emit_fop2(struct sljit_compiler
*compiler
, sljit_s32 op
,
1982 sljit_s32 dst
, sljit_sw dstw
,
1983 sljit_s32 src1
, sljit_sw src1w
,
1984 sljit_s32 src2
, sljit_sw src2w
)
1986 sljit_s32 dst_r
, flags
= 0;
1989 CHECK(check_sljit_emit_fop2(compiler
, op
, dst
, dstw
, src1
, src1w
, src2
, src2w
));
1990 ADJUST_LOCAL_OFFSET(dst
, dstw
);
1991 ADJUST_LOCAL_OFFSET(src1
, src1w
);
1992 ADJUST_LOCAL_OFFSET(src2
, src2w
);
1994 compiler
->cache_arg
= 0;
1995 compiler
->cache_argw
= 0;
1997 dst_r
= FAST_IS_REG(dst
) ? dst
: TMP_FREG2
;
1999 if (src1
& SLJIT_MEM
) {
2000 if (getput_arg_fast(compiler
, FLOAT_DATA(op
) | LOAD_DATA
, TMP_FREG1
, src1
, src1w
)) {
2001 FAIL_IF(compiler
->error
);
2007 if (src2
& SLJIT_MEM
) {
2008 if (getput_arg_fast(compiler
, FLOAT_DATA(op
) | LOAD_DATA
, TMP_FREG2
, src2
, src2w
)) {
2009 FAIL_IF(compiler
->error
);
2015 if ((flags
& (SLOW_SRC1
| SLOW_SRC2
)) == (SLOW_SRC1
| SLOW_SRC2
)) {
2016 if (!can_cache(src1
, src1w
, src2
, src2w
) && can_cache(src1
, src1w
, dst
, dstw
)) {
2017 FAIL_IF(getput_arg(compiler
, FLOAT_DATA(op
) | LOAD_DATA
, TMP_FREG2
, src2
, src2w
, src1
, src1w
));
2018 FAIL_IF(getput_arg(compiler
, FLOAT_DATA(op
) | LOAD_DATA
, TMP_FREG1
, src1
, src1w
, dst
, dstw
));
2021 FAIL_IF(getput_arg(compiler
, FLOAT_DATA(op
) | LOAD_DATA
, TMP_FREG1
, src1
, src1w
, src2
, src2w
));
2022 FAIL_IF(getput_arg(compiler
, FLOAT_DATA(op
) | LOAD_DATA
, TMP_FREG2
, src2
, src2w
, dst
, dstw
));
2025 else if (flags
& SLOW_SRC1
)
2026 FAIL_IF(getput_arg(compiler
, FLOAT_DATA(op
) | LOAD_DATA
, TMP_FREG1
, src1
, src1w
, dst
, dstw
));
2027 else if (flags
& SLOW_SRC2
)
2028 FAIL_IF(getput_arg(compiler
, FLOAT_DATA(op
) | LOAD_DATA
, TMP_FREG2
, src2
, src2w
, dst
, dstw
));
2030 if (flags
& SLOW_SRC1
)
2032 if (flags
& SLOW_SRC2
)
2035 switch (GET_OPCODE(op
)) {
2037 FAIL_IF(push_inst(compiler
, FADD_S
| FMT(op
) | FRD(dst_r
) | FRS1(src1
) | FRS2(src2
)));
2041 FAIL_IF(push_inst(compiler
, FSUB_S
| FMT(op
) | FRD(dst_r
) | FRS1(src1
) | FRS2(src2
)));
2045 FAIL_IF(push_inst(compiler
, FMUL_S
| FMT(op
) | FRD(dst_r
) | FRS1(src1
) | FRS2(src2
)));
2049 FAIL_IF(push_inst(compiler
, FDIV_S
| FMT(op
) | FRD(dst_r
) | FRS1(src1
) | FRS2(src2
)));
2053 if (dst_r
== TMP_FREG2
)
2054 FAIL_IF(emit_op_mem2(compiler
, FLOAT_DATA(op
), TMP_FREG2
, dst
, dstw
, 0, 0));
2056 return SLJIT_SUCCESS
;
2062 /* --------------------------------------------------------------------- */
2063 /* Other instructions */
2064 /* --------------------------------------------------------------------- */
2066 SLJIT_API_FUNC_ATTRIBUTE sljit_s32
sljit_emit_fast_enter(struct sljit_compiler
*compiler
, sljit_s32 dst
, sljit_sw dstw
)
2069 CHECK(check_sljit_emit_fast_enter(compiler
, dst
, dstw
));
2070 ADJUST_LOCAL_OFFSET(dst
, dstw
);
2072 if (FAST_IS_REG(dst
))
2073 return push_inst(compiler
, ADDI
| RD(dst
) | RS1(RETURN_ADDR_REG
) | IMM_I(0));
2076 return emit_op_mem(compiler
, WORD_DATA
, RETURN_ADDR_REG
, dst
, dstw
);
2079 /* --------------------------------------------------------------------- */
2080 /* Conditional instructions */
2081 /* --------------------------------------------------------------------- */
2083 SLJIT_API_FUNC_ATTRIBUTE
struct sljit_label
* sljit_emit_label(struct sljit_compiler
*compiler
)
2085 struct sljit_label
*label
;
2088 CHECK_PTR(check_sljit_emit_label(compiler
));
2090 if (compiler
->last_label
&& compiler
->last_label
->size
== compiler
->size
)
2091 return compiler
->last_label
;
2093 label
= (struct sljit_label
*)ensure_abuf(compiler
, sizeof(struct sljit_label
));
2094 PTR_FAIL_IF(!label
);
2095 set_label(label
, compiler
);
2099 #if (defined SLJIT_CONFIG_RISCV_32 && SLJIT_CONFIG_RISCV_32)
2100 #define BRANCH_LENGTH ((sljit_ins)(3 * sizeof(sljit_ins)) << 7)
2102 #define BRANCH_LENGTH ((sljit_ins)(7 * sizeof(sljit_ins)) << 7)
2105 SLJIT_API_FUNC_ATTRIBUTE
struct sljit_jump
* sljit_emit_jump(struct sljit_compiler
*compiler
, sljit_s32 type
)
2107 struct sljit_jump
*jump
;
2111 CHECK_PTR(check_sljit_emit_jump(compiler
, type
));
2113 jump
= (struct sljit_jump
*)ensure_abuf(compiler
, sizeof(struct sljit_jump
));
2115 set_jump(jump
, compiler
, type
& SLJIT_REWRITABLE_JUMP
);
2120 inst
= BNE
| RS1(EQUAL_FLAG
) | RS2(TMP_ZERO
) | BRANCH_LENGTH
;
2122 case SLJIT_NOT_EQUAL
:
2123 inst
= BEQ
| RS1(EQUAL_FLAG
) | RS2(TMP_ZERO
) | BRANCH_LENGTH
;
2127 case SLJIT_SIG_LESS
:
2128 case SLJIT_SIG_GREATER
:
2129 case SLJIT_OVERFLOW
:
2132 case SLJIT_ORDERED_EQUAL
:
2133 case SLJIT_ORDERED_NOT_EQUAL
: /* Not supported. */
2135 case SLJIT_ORDERED_LESS
:
2136 case SLJIT_ORDERED_GREATER
:
2137 case SLJIT_F_LESS_EQUAL
:
2138 case SLJIT_ORDERED_LESS_EQUAL
:
2139 case SLJIT_ORDERED_GREATER_EQUAL
:
2141 inst
= BEQ
| RS1(OTHER_FLAG
) | RS2(TMP_ZERO
) | BRANCH_LENGTH
;
2143 case SLJIT_GREATER_EQUAL
:
2144 case SLJIT_LESS_EQUAL
:
2145 case SLJIT_SIG_GREATER_EQUAL
:
2146 case SLJIT_SIG_LESS_EQUAL
:
2147 case SLJIT_NOT_OVERFLOW
:
2148 case SLJIT_NOT_CARRY
:
2149 case SLJIT_F_NOT_EQUAL
:
2150 case SLJIT_UNORDERED_OR_NOT_EQUAL
:
2151 case SLJIT_UNORDERED_OR_EQUAL
: /* Not supported. */
2152 case SLJIT_F_GREATER_EQUAL
:
2153 case SLJIT_UNORDERED_OR_GREATER_EQUAL
:
2154 case SLJIT_UNORDERED_OR_LESS_EQUAL
:
2155 case SLJIT_F_GREATER
:
2156 case SLJIT_UNORDERED_OR_GREATER
:
2157 case SLJIT_UNORDERED_OR_LESS
:
2158 case SLJIT_UNORDERED
:
2159 inst
= BNE
| RS1(OTHER_FLAG
) | RS2(TMP_ZERO
) | BRANCH_LENGTH
;
2162 /* Not conditional branch. */
2168 PTR_FAIL_IF(push_inst(compiler
, inst
));
2169 jump
->flags
|= IS_COND
;
2172 jump
->addr
= compiler
->size
;
2173 inst
= JALR
| RS1(TMP_REG1
) | IMM_I(0);
2175 if (type
>= SLJIT_FAST_CALL
) {
2176 jump
->flags
|= IS_CALL
;
2177 inst
|= RD(RETURN_ADDR_REG
);
2180 PTR_FAIL_IF(push_inst(compiler
, inst
));
2182 /* Maximum number of instructions required for generating a constant. */
2183 #if (defined SLJIT_CONFIG_RISCV_32 && SLJIT_CONFIG_RISCV_32)
2184 compiler
->size
+= 1;
2186 compiler
->size
+= 5;
2191 SLJIT_API_FUNC_ATTRIBUTE
struct sljit_jump
* sljit_emit_call(struct sljit_compiler
*compiler
, sljit_s32 type
,
2192 sljit_s32 arg_types
)
2194 SLJIT_UNUSED_ARG(arg_types
);
2196 CHECK_PTR(check_sljit_emit_call(compiler
, type
, arg_types
));
2198 if (type
& SLJIT_CALL_RETURN
) {
2199 PTR_FAIL_IF(emit_stack_frame_release(compiler
));
2200 type
= SLJIT_JUMP
| (type
& SLJIT_REWRITABLE_JUMP
);
2203 SLJIT_SKIP_CHECKS(compiler
);
2204 return sljit_emit_jump(compiler
, type
);
2207 SLJIT_API_FUNC_ATTRIBUTE
struct sljit_jump
* sljit_emit_cmp(struct sljit_compiler
*compiler
, sljit_s32 type
,
2208 sljit_s32 src1
, sljit_sw src1w
,
2209 sljit_s32 src2
, sljit_sw src2w
)
2211 struct sljit_jump
*jump
;
2216 CHECK_PTR(check_sljit_emit_cmp(compiler
, type
, src1
, src1w
, src2
, src2w
));
2217 ADJUST_LOCAL_OFFSET(src1
, src1w
);
2218 ADJUST_LOCAL_OFFSET(src2
, src2w
);
2220 compiler
->cache_arg
= 0;
2221 compiler
->cache_argw
= 0;
2222 #if (defined SLJIT_CONFIG_RISCV_32 && SLJIT_CONFIG_RISCV_32)
2223 flags
= WORD_DATA
| LOAD_DATA
;
2224 #else /* !SLJIT_CONFIG_RISCV_32 */
2225 flags
= ((type
& SLJIT_32
) ? INT_DATA
: WORD_DATA
) | LOAD_DATA
;
2226 #endif /* SLJIT_CONFIG_RISCV_32 */
2228 if (src1
& SLJIT_MEM
) {
2229 PTR_FAIL_IF(emit_op_mem2(compiler
, flags
, TMP_REG1
, src1
, src1w
, src2
, src2w
));
2233 if (src2
& SLJIT_MEM
) {
2234 PTR_FAIL_IF(emit_op_mem2(compiler
, flags
, TMP_REG2
, src2
, src2w
, 0, 0));
2238 if (src1
& SLJIT_IMM
) {
2240 PTR_FAIL_IF(load_immediate(compiler
, TMP_REG1
, src1w
, TMP_REG3
));
2247 if (src2
& SLJIT_IMM
) {
2249 PTR_FAIL_IF(load_immediate(compiler
, TMP_REG2
, src2w
, TMP_REG3
));
2256 jump
= (struct sljit_jump
*)ensure_abuf(compiler
, sizeof(struct sljit_jump
));
2258 set_jump(jump
, compiler
, (sljit_u32
)((type
& SLJIT_REWRITABLE_JUMP
) | IS_COND
));
2263 inst
= BNE
| RS1(src1
) | RS2(src2
) | BRANCH_LENGTH
;
2265 case SLJIT_NOT_EQUAL
:
2266 inst
= BEQ
| RS1(src1
) | RS2(src2
) | BRANCH_LENGTH
;
2269 inst
= BGEU
| RS1(src1
) | RS2(src2
) | BRANCH_LENGTH
;
2271 case SLJIT_GREATER_EQUAL
:
2272 inst
= BLTU
| RS1(src1
) | RS2(src2
) | BRANCH_LENGTH
;
2275 inst
= BGEU
| RS1(src2
) | RS2(src1
) | BRANCH_LENGTH
;
2277 case SLJIT_LESS_EQUAL
:
2278 inst
= BLTU
| RS1(src2
) | RS2(src1
) | BRANCH_LENGTH
;
2280 case SLJIT_SIG_LESS
:
2281 inst
= BGE
| RS1(src1
) | RS2(src2
) | BRANCH_LENGTH
;
2283 case SLJIT_SIG_GREATER_EQUAL
:
2284 inst
= BLT
| RS1(src1
) | RS2(src2
) | BRANCH_LENGTH
;
2286 case SLJIT_SIG_GREATER
:
2287 inst
= BGE
| RS1(src2
) | RS2(src1
) | BRANCH_LENGTH
;
2289 case SLJIT_SIG_LESS_EQUAL
:
2290 inst
= BLT
| RS1(src2
) | RS2(src1
) | BRANCH_LENGTH
;
2294 PTR_FAIL_IF(push_inst(compiler
, inst
));
2296 jump
->addr
= compiler
->size
;
2297 PTR_FAIL_IF(push_inst(compiler
, JALR
| RD(TMP_ZERO
) | RS1(TMP_REG1
) | IMM_I(0)));
2299 /* Maximum number of instructions required for generating a constant. */
2300 #if (defined SLJIT_CONFIG_RISCV_32 && SLJIT_CONFIG_RISCV_32)
2301 compiler
->size
+= 1;
2303 compiler
->size
+= 5;
2308 #undef BRANCH_LENGTH
2310 SLJIT_API_FUNC_ATTRIBUTE sljit_s32
sljit_emit_ijump(struct sljit_compiler
*compiler
, sljit_s32 type
, sljit_s32 src
, sljit_sw srcw
)
2312 struct sljit_jump
*jump
;
2315 CHECK(check_sljit_emit_ijump(compiler
, type
, src
, srcw
));
2316 ADJUST_LOCAL_OFFSET(src
, srcw
);
2318 if (!(src
& SLJIT_IMM
)) {
2319 if (src
& SLJIT_MEM
) {
2320 FAIL_IF(emit_op_mem(compiler
, WORD_DATA
| LOAD_DATA
, TMP_REG1
, src
, srcw
));
2323 return push_inst(compiler
, JALR
| RD((type
>= SLJIT_FAST_CALL
) ? RETURN_ADDR_REG
: TMP_ZERO
) | RS1(src
) | IMM_I(0));
2326 /* These jumps are converted to jump/call instructions when possible. */
2327 jump
= (struct sljit_jump
*)ensure_abuf(compiler
, sizeof(struct sljit_jump
));
2329 set_jump(jump
, compiler
, JUMP_ADDR
| ((type
>= SLJIT_FAST_CALL
) ? IS_CALL
: 0));
2330 jump
->u
.target
= (sljit_uw
)srcw
;
2332 jump
->addr
= compiler
->size
;
2333 FAIL_IF(push_inst(compiler
, JALR
| RD((type
>= SLJIT_FAST_CALL
) ? RETURN_ADDR_REG
: TMP_ZERO
) | RS1(TMP_REG1
) | IMM_I(0)));
2335 /* Maximum number of instructions required for generating a constant. */
2336 #if (defined SLJIT_CONFIG_RISCV_32 && SLJIT_CONFIG_RISCV_32)
2337 compiler
->size
+= 1;
2339 compiler
->size
+= 5;
2341 return SLJIT_SUCCESS
;
2344 SLJIT_API_FUNC_ATTRIBUTE sljit_s32
sljit_emit_icall(struct sljit_compiler
*compiler
, sljit_s32 type
,
2345 sljit_s32 arg_types
,
2346 sljit_s32 src
, sljit_sw srcw
)
2348 SLJIT_UNUSED_ARG(arg_types
);
2350 CHECK(check_sljit_emit_icall(compiler
, type
, arg_types
, src
, srcw
));
2351 ADJUST_LOCAL_OFFSET(src
, srcw
);
2353 if (src
& SLJIT_MEM
) {
2354 FAIL_IF(emit_op_mem(compiler
, WORD_DATA
| LOAD_DATA
, TMP_REG1
, src
, srcw
));
2358 if (type
& SLJIT_CALL_RETURN
) {
2359 if (src
>= SLJIT_FIRST_SAVED_REG
&& src
<= SLJIT_S0
) {
2360 FAIL_IF(push_inst(compiler
, ADDI
| RD(TMP_REG1
) | RS1(src
) | IMM_I(0)));
2364 FAIL_IF(emit_stack_frame_release(compiler
));
2368 SLJIT_SKIP_CHECKS(compiler
);
2369 return sljit_emit_ijump(compiler
, type
, src
, srcw
);
2372 SLJIT_API_FUNC_ATTRIBUTE sljit_s32
sljit_emit_op_flags(struct sljit_compiler
*compiler
, sljit_s32 op
,
2373 sljit_s32 dst
, sljit_sw dstw
,
2376 sljit_s32 src_r
, dst_r
, invert
;
2377 sljit_s32 saved_op
= op
;
2378 #if (defined SLJIT_CONFIG_RISCV_32 && SLJIT_CONFIG_RISCV_32)
2379 sljit_s32 mem_type
= WORD_DATA
;
2381 sljit_s32 mem_type
= ((op
& SLJIT_32
) || op
== SLJIT_MOV32
) ? (INT_DATA
| SIGNED_DATA
) : WORD_DATA
;
2385 CHECK(check_sljit_emit_op_flags(compiler
, op
, dst
, dstw
, type
));
2386 ADJUST_LOCAL_OFFSET(dst
, dstw
);
2388 op
= GET_OPCODE(op
);
2389 dst_r
= (op
< SLJIT_ADD
&& FAST_IS_REG(dst
)) ? dst
: TMP_REG2
;
2391 compiler
->cache_arg
= 0;
2392 compiler
->cache_argw
= 0;
2394 if (op
>= SLJIT_ADD
&& (dst
& SLJIT_MEM
))
2395 FAIL_IF(emit_op_mem2(compiler
, mem_type
| LOAD_DATA
, TMP_REG1
, dst
, dstw
, dst
, dstw
));
2397 if (type
< SLJIT_F_EQUAL
) {
2399 invert
= type
& 0x1;
2403 case SLJIT_NOT_EQUAL
:
2404 FAIL_IF(push_inst(compiler
, SLTUI
| RD(dst_r
) | RS1(EQUAL_FLAG
) | IMM_I(1)));
2407 case SLJIT_OVERFLOW
:
2408 case SLJIT_NOT_OVERFLOW
:
2409 if (compiler
->status_flags_state
& (SLJIT_CURRENT_FLAGS_ADD
| SLJIT_CURRENT_FLAGS_SUB
)) {
2413 FAIL_IF(push_inst(compiler
, SLTUI
| RD(dst_r
) | RS1(OTHER_FLAG
) | IMM_I(1)));
2423 case SLJIT_F_NOT_EQUAL
:
2424 case SLJIT_UNORDERED_OR_NOT_EQUAL
:
2425 case SLJIT_UNORDERED_OR_EQUAL
: /* Not supported. */
2426 case SLJIT_F_GREATER_EQUAL
:
2427 case SLJIT_UNORDERED_OR_GREATER_EQUAL
:
2428 case SLJIT_UNORDERED_OR_LESS_EQUAL
:
2429 case SLJIT_F_GREATER
:
2430 case SLJIT_UNORDERED_OR_GREATER
:
2431 case SLJIT_UNORDERED_OR_LESS
:
2432 case SLJIT_UNORDERED
:
2439 FAIL_IF(push_inst(compiler
, XORI
| RD(dst_r
) | RS1(src_r
) | IMM_I(1)));
2443 if (op
< SLJIT_ADD
) {
2444 if (dst
& SLJIT_MEM
)
2445 return emit_op_mem(compiler
, mem_type
, src_r
, dst
, dstw
);
2448 return push_inst(compiler
, ADDI
| RD(dst_r
) | RS1(src_r
) | IMM_I(0));
2449 return SLJIT_SUCCESS
;
2452 mem_type
|= CUMULATIVE_OP
| IMM_OP
| ALT_KEEP_CACHE
;
2454 if (dst
& SLJIT_MEM
)
2455 return emit_op(compiler
, saved_op
, mem_type
, dst
, dstw
, TMP_REG1
, 0, src_r
, 0);
2456 return emit_op(compiler
, saved_op
, mem_type
, dst
, dstw
, dst
, dstw
, src_r
, 0);
2459 SLJIT_API_FUNC_ATTRIBUTE sljit_s32
sljit_emit_cmov(struct sljit_compiler
*compiler
, sljit_s32 type
,
2461 sljit_s32 src
, sljit_sw srcw
)
2464 CHECK(check_sljit_emit_cmov(compiler
, type
, dst_reg
, src
, srcw
));
2466 return sljit_emit_cmov_generic(compiler
, type
, dst_reg
, src
, srcw
);;
2469 SLJIT_API_FUNC_ATTRIBUTE
struct sljit_const
* sljit_emit_const(struct sljit_compiler
*compiler
, sljit_s32 dst
, sljit_sw dstw
, sljit_sw init_value
)
2471 struct sljit_const
*const_
;
2475 CHECK_PTR(check_sljit_emit_const(compiler
, dst
, dstw
, init_value
));
2476 ADJUST_LOCAL_OFFSET(dst
, dstw
);
2478 const_
= (struct sljit_const
*)ensure_abuf(compiler
, sizeof(struct sljit_const
));
2479 PTR_FAIL_IF(!const_
);
2480 set_const(const_
, compiler
);
2482 dst_r
= FAST_IS_REG(dst
) ? dst
: TMP_REG2
;
2483 PTR_FAIL_IF(emit_const(compiler
, dst_r
, init_value
, ADDI
| RD(dst_r
)));
2485 if (dst
& SLJIT_MEM
)
2486 PTR_FAIL_IF(emit_op_mem(compiler
, WORD_DATA
, TMP_REG2
, dst
, dstw
));
2491 SLJIT_API_FUNC_ATTRIBUTE
struct sljit_put_label
* sljit_emit_put_label(struct sljit_compiler
*compiler
, sljit_s32 dst
, sljit_sw dstw
)
2493 struct sljit_put_label
*put_label
;
2497 CHECK_PTR(check_sljit_emit_put_label(compiler
, dst
, dstw
));
2498 ADJUST_LOCAL_OFFSET(dst
, dstw
);
2500 put_label
= (struct sljit_put_label
*)ensure_abuf(compiler
, sizeof(struct sljit_put_label
));
2501 PTR_FAIL_IF(!put_label
);
2502 set_put_label(put_label
, compiler
, 0);
2504 dst_r
= FAST_IS_REG(dst
) ? dst
: TMP_REG2
;
2505 PTR_FAIL_IF(push_inst(compiler
, (sljit_ins
)dst_r
));
2506 #if (defined SLJIT_CONFIG_RISCV_32 && SLJIT_CONFIG_RISCV_32)
2507 compiler
->size
+= 1;
2509 compiler
->size
+= 5;
2512 if (dst
& SLJIT_MEM
)
2513 PTR_FAIL_IF(emit_op_mem(compiler
, WORD_DATA
, TMP_REG2
, dst
, dstw
));
2518 SLJIT_API_FUNC_ATTRIBUTE
void sljit_set_const(sljit_uw addr
, sljit_sw new_constant
, sljit_sw executable_offset
)
2520 sljit_set_jump_addr(addr
, (sljit_uw
)new_constant
, executable_offset
);