Improve sljit abi calling convention
[sljit.git] / sljit_src / sljitNativeRISCV_common.c
blobcc7d4a0e7bb12b8085e8e419b2d3a47dd9f3cc82
1 /*
2 * Stack-less Just-In-Time compiler
4 * Copyright Zoltan Herczeg (hzmester@freemail.hu). All rights reserved.
6 * Redistribution and use in source and binary forms, with or without modification, are
7 * permitted provided that the following conditions are met:
9 * 1. Redistributions of source code must retain the above copyright notice, this list of
10 * conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright notice, this list
13 * of conditions and the following disclaimer in the documentation and/or other materials
14 * provided with the distribution.
16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) AND CONTRIBUTORS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
18 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
19 * SHALL THE COPYRIGHT HOLDER(S) OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
20 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
21 * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
22 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
23 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
24 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 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)
43 #define TMP_ZERO 0
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)
150 #endif
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));
155 FAIL_IF(!ptr);
156 *ptr = ins;
157 compiler->size++;
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)
168 sljit_sw diff;
169 sljit_uw target_addr;
170 sljit_ins *inst;
172 inst = (sljit_ins *)jump->addr;
174 if (jump->flags & SLJIT_REWRITABLE_JUMP)
175 goto exit;
177 if (jump->flags & JUMP_ADDR)
178 target_addr = jump->u.target;
179 else {
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) {
187 inst--;
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;
194 return inst;
197 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;
205 #else
206 inst[-1] -= (sljit_ins)(5 * sizeof(sljit_ins)) << 7;
207 #endif
210 jump->flags |= PATCH_J;
211 return inst;
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;
220 inst[1] = inst[0];
221 return inst + 1;
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;
229 inst[1] = inst[0];
230 return inst + 1;
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;
238 inst[3] = inst[0];
239 return inst + 4;
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;
247 inst[4] = inst[0];
248 return inst + 4;
250 #endif
252 exit:
253 #if (defined SLJIT_CONFIG_RISCV_32 && SLJIT_CONFIG_RISCV_32)
254 inst[1] = inst[0];
255 return inst + 1;
256 #else
257 inst[5] = inst[0];
258 return inst + 5;
259 #endif
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;
268 return 1;
271 if (max_label <= S44_MAX) {
272 put_label->flags = PATCH_ABS44;
273 return 3;
276 if (max_label <= S52_MAX) {
277 put_label->flags = PATCH_ABS52;
278 return 4;
281 put_label->flags = 0;
282 return 5;
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;
291 sljit_uw flags;
292 sljit_ins *inst;
293 #if (defined SLJIT_CONFIG_RISCV_64 && SLJIT_CONFIG_RISCV_64)
294 sljit_sw high;
295 #endif
296 sljit_uw addr;
298 if (reg != 0) {
299 jump = (struct sljit_jump*)dst;
300 flags = jump->flags;
301 inst = (sljit_ins*)jump->addr;
302 addr = (flags & JUMP_LABEL) ? jump->u.label->addr : jump->u.target;
303 } else {
304 put_label = (struct sljit_put_label*)dst;
305 #if (defined SLJIT_CONFIG_RISCV_64 && SLJIT_CONFIG_RISCV_64)
306 flags = put_label->flags;
307 #endif
308 inst = (sljit_ins*)put_label->addr;
309 addr = put_label->label->addr;
310 reg = *inst;
313 if ((addr & 0x800) != 0)
314 addr += 0x1000;
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);
331 } else {
332 if ((high & 0x800) != 0)
333 high += 0x1000;
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);
340 inst += 2;
341 } else {
342 high = (sljit_sw)addr >> 32;
344 if ((addr & 0x80000000l) != 0)
345 high = ~high;
347 if ((high & 0x800) != 0)
348 high += 0x1000;
350 if (flags & PATCH_ABS52) {
351 SLJIT_ASSERT(addr <= S52_MAX);
352 inst[0] = LUI | RD(TMP_REG3) | (sljit_ins)(high << 12);
353 } else {
354 inst[0] = LUI | RD(TMP_REG3) | (sljit_ins)(high & ~0xfff);
355 inst[1] = ADDI | RD(TMP_REG3) | RS1(TMP_REG3) | IMM_I(high);
356 inst++;
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);
362 inst += 3;
364 #endif /* !SLJIT_CONFIG_RISCV_32 */
366 if (jump != NULL) {
367 SLJIT_ASSERT((inst[1] & 0x707f) == JALR);
368 inst[1] = (inst[1] & 0xfffff) | IMM_I(addr);
369 } else
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;
376 sljit_ins *code;
377 sljit_ins *code_ptr;
378 sljit_ins *buf_ptr;
379 sljit_ins *buf_end;
380 sljit_uw word_count;
381 sljit_uw next_addr;
382 sljit_sw executable_offset;
383 sljit_uw addr;
385 struct sljit_label *label;
386 struct sljit_jump *jump;
387 struct sljit_const *const_;
388 struct sljit_put_label *put_label;
390 CHECK_ERROR_PTR();
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);
396 buf = compiler->buf;
398 code_ptr = code;
399 word_count = 0;
400 next_addr = 0;
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;
408 do {
409 buf_ptr = (sljit_ins*)buf->memory;
410 buf_end = buf_ptr + (buf->used_size >> 2);
411 do {
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);
423 label = label->next;
425 if (jump && jump->addr == word_count) {
426 #if (defined SLJIT_CONFIG_RISCV_32 && SLJIT_CONFIG_RISCV_32)
427 word_count += 1;
428 #else
429 word_count += 5;
430 #endif
431 jump->addr = (sljit_uw)code_ptr;
432 code_ptr = detect_jump_type(jump, code, executable_offset);
433 jump = jump->next;
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)
443 code_ptr += 1;
444 word_count += 1;
445 #else
446 code_ptr += put_label_get_length(put_label, (sljit_uw)(SLJIT_ADD_EXEC_OFFSET(code, executable_offset) + put_label->label->size));
447 word_count += 5;
448 #endif
449 put_label = put_label->next;
451 next_addr = compute_next_addr(label, jump, const_, put_label);
453 code_ptr++;
454 word_count++;
455 } while (buf_ptr < buf_end);
457 buf = buf->next;
458 } while (buf);
460 if (label && label->size == word_count) {
461 label->addr = (sljit_uw)code_ptr;
462 label->size = (sljit_uw)(code_ptr - code);
463 label = label->next;
466 SLJIT_ASSERT(!label);
467 SLJIT_ASSERT(!jump);
468 SLJIT_ASSERT(!const_);
469 SLJIT_ASSERT(!put_label);
470 SLJIT_ASSERT(code_ptr - code <= (sljit_sw)compiler->size);
472 jump = compiler->jumps;
473 while (jump) {
474 do {
475 if (!(jump->flags & (PATCH_B | PATCH_J | PATCH_REL32))) {
476 load_addr_to_reg(jump, TMP_REG1);
477 break;
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;
488 break;
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)
496 addr += 0x1000;
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);
501 break;
503 #endif
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;
508 } while (0);
509 jump = jump->next;
512 put_label = compiler->put_labels;
513 while (put_label) {
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);
527 return code;
530 SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_has_cpu_feature(sljit_s32 feature_type)
532 switch (feature_type) {
533 case SLJIT_HAS_FPU:
534 case SLJIT_HAS_ZERO_REGISTER:
535 return 1;
536 default:
537 return 0;
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 /* --------------------------------------------------------------------- */
547 /* Entry, exit */
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 */
558 #define GPR_REG 0x0f
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
582 #else
583 #define STACK_STORE SD
584 #define STACK_LOAD LD
585 #endif
587 #if (defined SLJIT_CONFIG_RISCV_32 && SLJIT_CONFIG_RISCV_32)
588 #include "sljitNativeRISCV_32.c"
589 #else
590 #include "sljitNativeRISCV_64.c"
591 #endif
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);
602 CHECK_ERROR();
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));
613 #else
614 local_size += GET_SAVED_FLOAT_REGISTERS_SIZE(fscratches, fsaveds, sizeof(sljit_f64));
615 #endif
616 local_size = (local_size + SLJIT_LOCALS_OFFSET + 15) & ~0xf;
617 compiler->local_size = local_size;
619 if (local_size <= STACK_MAX_DISTANCE) {
620 /* Frequent case. */
621 FAIL_IF(push_inst(compiler, ADDI | RD(SLJIT_SP) | RS1(SLJIT_SP) | IMM_I(-local_size)));
622 offset = local_size - SSIZE_OF(sw);
623 local_size = 0;
624 } else {
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);
650 #endif
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;
672 saved_arg_count = 0;
673 tmp = SLJIT_R0;
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)));
679 saved_arg_count++;
681 tmp++;
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)
696 CHECK_ERROR();
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));
707 #else
708 local_size += GET_SAVED_FLOAT_REGISTERS_SIZE(fscratches, fsaveds, sizeof(sljit_f64));
709 #endif
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)));
728 } else
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);
754 #endif
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)
774 CHECK_ERROR();
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 /* --------------------------------------------------------------------- */
782 /* Operators */
783 /* --------------------------------------------------------------------- */
785 #if (defined SLJIT_CONFIG_RISCV_32 && SLJIT_CONFIG_RISCV_32)
786 #define ARCH_32_64(a, b) a
787 #else
788 #define ARCH_32_64(a, b) b
789 #endif
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 */,
816 #undef ARCH_32_64
818 static sljit_s32 push_mem_inst(struct sljit_compiler *compiler, sljit_s32 flags, sljit_s32 reg, sljit_s32 base, sljit_sw offset)
820 sljit_ins ins;
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);
827 else
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))
842 return 1;
844 FAIL_IF(push_mem_inst(compiler, flags, reg, arg & REG_MASK, argw));
845 return -1;
847 return 0;
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) {
860 argw &= 0x3;
861 next_argw &= 0x3;
862 if (argw && argw == next_argw && (arg == next_arg || (arg & OFFS_REG_MASK) == (next_arg & OFFS_REG_MASK)))
863 return 1;
864 return 0;
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))
870 return 1;
871 return 0;
874 return 0;
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)) {
886 next_arg = 0;
887 next_argw = 0;
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))
893 tmp_r = reg;
895 if (SLJIT_UNLIKELY(arg & OFFS_REG_MASK)) {
896 argw &= 0x3;
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)));
925 tmp_r = TMP_REG3;
927 else
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;
937 } else {
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;
945 offset = 0;
946 } else {
947 FAIL_IF(load_immediate(compiler, TMP_REG3, argw_hi, tmp_r));
948 compiler->cache_argw = argw_hi;
949 offset = argw & 0xfff;
950 argw = argw_hi;
954 if (!base)
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))
976 tmp_r = reg;
978 if (SLJIT_UNLIKELY(arg & OFFS_REG_MASK)) {
979 argw &= 0x3;
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)));
985 else
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));
992 if (base != 0)
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);
998 #undef TO_ARGW_HI
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)
1008 #define WORD 0
1009 #define IMM_EXTEND(v) (IMM_I(v))
1010 #else /* !SLJIT_CONFIG_RISCV_32 */
1011 #define WORD word
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))); \
1022 else { \
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))); \
1036 else { \
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)) {
1054 case SLJIT_MOV:
1055 SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & SRC2_IMM));
1056 if (dst != src2)
1057 return push_inst(compiler, ADDI | RD(dst) | RS1(src2) | IMM_I(0));
1058 return SLJIT_SUCCESS;
1060 case SLJIT_MOV_U8:
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;
1067 case SLJIT_MOV_S8:
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;
1076 case SLJIT_MOV_U16:
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;
1085 case SLJIT_MOV_S16:
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)
1095 case SLJIT_MOV_U32:
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;
1104 case SLJIT_MOV_S32:
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 */
1112 case SLJIT_CLZ:
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)));
1122 } else {
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 */
1127 /* Check zero. */
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;
1137 case SLJIT_ADD:
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) {
1143 if (is_overflow) {
1144 if (src2 >= 0)
1145 FAIL_IF(push_inst(compiler, ADDI | RD(EQUAL_FLAG) | RS1(src1) | IMM_I(0)));
1146 else
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)));
1156 else {
1157 if (is_overflow)
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) {
1163 if (src1 != dst)
1164 carry_src_r = (sljit_s32)src1;
1165 else if (src2 != dst)
1166 carry_src_r = (sljit_s32)src2;
1167 else {
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)));
1182 else
1183 FAIL_IF(push_inst(compiler, SLTU | RD(OTHER_FLAG) | RS1(dst) | RS2(carry_src_r)));
1186 if (!is_overflow)
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));
1195 case SLJIT_ADDC:
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)));
1200 } else {
1201 if (carry_src_r != 0) {
1202 if (src1 != dst)
1203 carry_src_r = (sljit_s32)src1;
1204 else if (src2 != dst)
1205 carry_src_r = (sljit_s32)src2;
1206 else {
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)));
1219 else
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));
1233 case SLJIT_SUB:
1234 if ((flags & SRC2_IMM) && src2 == SIMM_MIN) {
1235 FAIL_IF(push_inst(compiler, ADDI | RD(TMP_REG2) | RS1(TMP_ZERO) | IMM_I(src2)));
1236 src2 = TMP_REG2;
1237 flags &= ~SRC2_IMM;
1240 is_handled = 0;
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)));
1245 is_handled = 1;
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)));
1249 is_handled = 1;
1253 if (!is_handled && GET_FLAG_TYPE(op) >= SLJIT_LESS && GET_FLAG_TYPE(op) <= SLJIT_SIG_LESS_EQUAL) {
1254 is_handled = 1;
1256 if (flags & SRC2_IMM) {
1257 FAIL_IF(push_inst(compiler, ADDI | RD(TMP_REG2) | RS1(TMP_ZERO) | IMM_I(src2)));
1258 src2 = TMP_REG2;
1259 flags &= ~SRC2_IMM;
1262 switch (GET_FLAG_TYPE(op)) {
1263 case SLJIT_LESS:
1264 case SLJIT_GREATER_EQUAL:
1265 FAIL_IF(push_inst(compiler, SLTU | RD(OTHER_FLAG) | RS1(src1) | RS2(src2)));
1266 break;
1267 case SLJIT_GREATER:
1268 case SLJIT_LESS_EQUAL:
1269 FAIL_IF(push_inst(compiler, SLTU | RD(OTHER_FLAG) | RS1(src2) | RS2(src1)));
1270 break;
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)));
1274 break;
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)));
1278 break;
1282 if (is_handled) {
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));
1289 else {
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) {
1302 if (is_overflow) {
1303 if (src2 >= 0)
1304 FAIL_IF(push_inst(compiler, ADDI | RD(EQUAL_FLAG) | RS1(src1) | IMM_I(0)));
1305 else
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)));
1318 else {
1319 if (is_overflow)
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)));
1332 if (!is_overflow)
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));
1341 case SLJIT_SUBC:
1342 if ((flags & SRC2_IMM) && src2 == SIMM_MIN) {
1343 FAIL_IF(push_inst(compiler, ADDI | RD(TMP_REG2) | RS1(TMP_ZERO) | IMM_I(src2)));
1344 src2 = TMP_REG2;
1345 flags &= ~SRC2_IMM;
1348 is_carry = GET_FLAG_TYPE(op) == GET_FLAG_TYPE(SLJIT_SET_CARRY);
1350 if (flags & SRC2_IMM) {
1351 if (is_carry)
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)));
1356 else {
1357 if (is_carry)
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)));
1363 if (is_carry)
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)));
1368 if (!is_carry)
1369 return SLJIT_SUCCESS;
1371 return push_inst(compiler, OR | RD(OTHER_FLAG) | RS1(EQUAL_FLAG) | RS2(TMP_REG1));
1373 case SLJIT_MUL:
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)
1380 if (word) {
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));
1396 case SLJIT_AND:
1397 EMIT_LOGICAL(ANDI, AND);
1398 return SLJIT_SUCCESS;
1400 case SLJIT_OR:
1401 EMIT_LOGICAL(ORI, OR);
1402 return SLJIT_SUCCESS;
1404 case SLJIT_XOR:
1405 EMIT_LOGICAL(XORI, XOR);
1406 return SLJIT_SUCCESS;
1408 case SLJIT_SHL:
1409 EMIT_SHIFT(SLLI, SLL);
1410 return SLJIT_SUCCESS;
1412 case SLJIT_LSHR:
1413 EMIT_SHIFT(SRLI, SRL);
1414 return SLJIT_SUCCESS;
1416 case SLJIT_ASHR:
1417 EMIT_SHIFT(SRAI, SRA);
1418 return SLJIT_SUCCESS;
1421 SLJIT_UNREACHABLE();
1422 return SLJIT_SUCCESS;
1425 #undef IMM_EXTEND
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;
1437 sljit_s32 src1_r;
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)) {
1451 dst_r = dst;
1452 flags |= REG_DEST;
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))
1457 flags |= SLOW_DEST;
1459 if (flags & IMM_OP) {
1460 if ((src2 & SLJIT_IMM) && src2w != 0 && src2w <= SIMM_MAX && src2w >= SIMM_MIN) {
1461 flags |= SRC2_IMM;
1462 src2_r = src2w;
1464 else if ((flags & CUMULATIVE_OP) && (src1 & SLJIT_IMM) && src1w != 0 && src1w <= SIMM_MAX && src1w >= SIMM_MIN) {
1465 flags |= SRC2_IMM;
1466 src2_r = src1w;
1468 /* And swap arguments. */
1469 src1 = src2;
1470 src1w = src2w;
1471 src2 = SLJIT_IMM;
1472 /* src2w = src2_r unneeded. */
1476 /* Source 1. */
1477 if (FAST_IS_REG(src1)) {
1478 src1_r = src1;
1479 flags |= REG1_SOURCE;
1481 else if (src1 & SLJIT_IMM) {
1482 if (src1w) {
1483 FAIL_IF(load_immediate(compiler, TMP_REG1, src1w, TMP_REG3));
1484 src1_r = TMP_REG1;
1486 else
1487 src1_r = TMP_ZERO;
1489 else {
1490 if (getput_arg_fast(compiler, flags | LOAD_DATA, TMP_REG1, src1, src1w))
1491 FAIL_IF(compiler->error);
1492 else
1493 flags |= SLOW_SRC1;
1494 src1_r = TMP_REG1;
1497 /* Source 2. */
1498 if (FAST_IS_REG(src2)) {
1499 src2_r = 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)) {
1506 if (src2w) {
1507 FAIL_IF(load_immediate(compiler, sugg_src2_r, src2w, TMP_REG3));
1508 src2_r = sugg_src2_r;
1510 else {
1511 src2_r = TMP_ZERO;
1512 if (flags & MOVE_OP) {
1513 if (dst & SLJIT_MEM)
1514 dst_r = 0;
1515 else
1516 op = SLJIT_MOV;
1521 else {
1522 if (getput_arg_fast(compiler, flags | LOAD_DATA, sugg_src2_r, src2, src2w))
1523 FAIL_IF(compiler->error);
1524 else
1525 flags |= SLOW_SRC2;
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));
1535 else {
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 */
1566 CHECK_ERROR();
1567 CHECK(check_sljit_emit_op0(compiler, op));
1569 switch (GET_OPCODE(op)) {
1570 case SLJIT_BREAKPOINT:
1571 return push_inst(compiler, EBREAK);
1572 case SLJIT_NOP:
1573 return push_inst(compiler, ADDI | RD(TMP_ZERO) | RS1(TMP_ZERO) | IMM_I(0));
1574 case SLJIT_LMUL_UW:
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));
1578 case SLJIT_LMUL_SW:
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));
1590 case SLJIT_DIV_UW:
1591 return push_inst(compiler, DIVU | WORD | RD(SLJIT_R0) | RS1(SLJIT_R0) | RS2(SLJIT_R1));
1592 case SLJIT_DIV_SW:
1593 return push_inst(compiler, DIV | WORD | RD(SLJIT_R0) | RS1(SLJIT_R0) | RS2(SLJIT_R1));
1594 case SLJIT_ENDBR:
1595 case SLJIT_SKIP_FRAMES_BEFORE_RETURN:
1596 return SLJIT_SUCCESS;
1599 return SLJIT_SUCCESS;
1602 #undef WORD
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;
1610 CHECK_ERROR();
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)
1616 if (op & SLJIT_32)
1617 flags = INT_DATA | SIGNED_DATA;
1618 #endif
1620 switch (GET_OPCODE(op)) {
1621 case SLJIT_MOV:
1622 #if (defined SLJIT_CONFIG_RISCV_32 && SLJIT_CONFIG_RISCV_32)
1623 case SLJIT_MOV_U32:
1624 case SLJIT_MOV_S32:
1625 case SLJIT_MOV32:
1626 #endif
1627 case SLJIT_MOV_P:
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)
1631 case SLJIT_MOV_U32:
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);
1634 case SLJIT_MOV_S32:
1635 /* Logical operators have no W variant, so sign extended input is necessary for them. */
1636 case SLJIT_MOV32:
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);
1638 #endif
1640 case SLJIT_MOV_U8:
1641 return emit_op(compiler, op, BYTE_DATA | MOVE_OP, dst, dstw, TMP_REG1, 0, src, (src & SLJIT_IMM) ? (sljit_u8)srcw : srcw);
1643 case SLJIT_MOV_S8:
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);
1646 case SLJIT_MOV_U16:
1647 return emit_op(compiler, op, HALF_DATA | MOVE_OP, dst, dstw, TMP_REG1, 0, src, (src & SLJIT_IMM) ? (sljit_u16)srcw : srcw);
1649 case SLJIT_MOV_S16:
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);
1652 case SLJIT_NOT:
1653 return emit_op(compiler, SLJIT_XOR | (op & (SLJIT_32 | SLJIT_SET_Z)), flags, dst, dstw, src, srcw, SLJIT_IMM, -1);
1655 case SLJIT_CLZ:
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;
1670 CHECK_ERROR();
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;
1684 #endif
1686 switch (GET_OPCODE(op)) {
1687 case SLJIT_ADD:
1688 case SLJIT_ADDC:
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);
1692 case SLJIT_SUB:
1693 case SLJIT_SUBC:
1694 compiler->status_flags_state = SLJIT_CURRENT_FLAGS_SUB;
1695 return emit_op(compiler, op, flags | IMM_OP, dst, dstw, src1, src1w, src2, src2w);
1697 case SLJIT_MUL:
1698 compiler->status_flags_state = 0;
1699 return emit_op(compiler, op, flags | CUMULATIVE_OP, dst, dstw, src1, src1w, src2, src2w);
1701 case SLJIT_AND:
1702 case SLJIT_OR:
1703 case SLJIT_XOR:
1704 return emit_op(compiler, op, flags | CUMULATIVE_OP | IMM_OP, dst, dstw, src1, src1w, src2, src2w);
1706 case SLJIT_SHL:
1707 case SLJIT_LSHR:
1708 case SLJIT_ASHR:
1709 #if (defined SLJIT_CONFIG_RISCV_32 && SLJIT_CONFIG_RISCV_32)
1710 if (src2 & SLJIT_IMM)
1711 src2w &= 0x1f;
1712 #else
1713 if (src2 & SLJIT_IMM) {
1714 if (op & SLJIT_32)
1715 src2w &= 0x1f;
1716 else
1717 src2w &= 0x3f;
1719 #endif
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)
1731 CHECK_ERROR();
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)
1741 CHECK_ERROR();
1742 CHECK(check_sljit_emit_op_src(compiler, op, src, srcw));
1743 ADJUST_LOCAL_OFFSET(src, srcw);
1745 switch (op) {
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)));
1749 else
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)
1780 CHECK_ERROR();
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
1799 #else
1800 sljit_u32 flags = ((sljit_u32)(GET_OPCODE(op) == SLJIT_CONV_SW_FROM_F64)) << 21;
1801 #endif
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));
1806 src = TMP_FREG1;
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);
1815 #else
1816 return emit_op_mem2(compiler, flags ? WORD_DATA : INT_DATA, TMP_REG2, dst, dstw, 0, 0);
1817 #endif
1819 return SLJIT_SUCCESS;
1821 #if (defined SLJIT_CONFIG_RISCV_32 && SLJIT_CONFIG_RISCV_32)
1822 # undef flags
1823 #endif
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)
1830 sljit_ins inst;
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;
1833 #endif
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));
1840 #else
1841 FAIL_IF(emit_op_mem2(compiler, (flags ? WORD_DATA : INT_DATA) | LOAD_DATA, TMP_REG1, src, srcw, dst, dstw));
1842 #endif
1843 src = TMP_REG1;
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;
1848 #endif
1850 FAIL_IF(load_immediate(compiler, TMP_REG1, srcw, TMP_REG3));
1851 src = TMP_REG1;
1854 inst = FCVT_S_W | FMT(op) | FRD(dst_r) | RS1(src);
1856 #if (defined SLJIT_CONFIG_RISCV_32 && SLJIT_CONFIG_RISCV_32)
1857 if (op & SLJIT_32)
1858 inst |= F3(0x7);
1859 #else
1860 inst |= flags;
1862 if (op != SLJIT_CONV_F64_FROM_S32)
1863 inst |= F3(0x7);
1864 #endif
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)
1877 sljit_ins inst;
1879 if (src1 & SLJIT_MEM) {
1880 FAIL_IF(emit_op_mem2(compiler, FLOAT_DATA(op) | LOAD_DATA, TMP_FREG1, src1, src1w, src2, src2w));
1881 src1 = TMP_FREG1;
1884 if (src2 & SLJIT_MEM) {
1885 FAIL_IF(emit_op_mem2(compiler, FLOAT_DATA(op) | LOAD_DATA, TMP_FREG2, src2, src2w, 0, 0));
1886 src2 = TMP_FREG2;
1889 switch (GET_FLAG_TYPE(op)) {
1890 case SLJIT_F_EQUAL:
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);
1895 break;
1896 case SLJIT_F_LESS:
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);
1901 break;
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);
1905 break;
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);
1911 break;
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);
1915 break;
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);
1921 break;
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);
1925 break;
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)
1935 sljit_s32 dst_r;
1937 CHECK_ERROR();
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)
1945 op ^= SLJIT_32;
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));
1951 src = dst_r;
1954 switch (GET_OPCODE(op)) {
1955 case SLJIT_MOV_F64:
1956 if (src != dst_r) {
1957 if (dst_r != TMP_FREG1)
1958 FAIL_IF(push_inst(compiler, FSGNJ_S | FMT(op) | FRD(dst_r) | FRS1(src) | FRS2(src)));
1959 else
1960 dst_r = src;
1962 break;
1963 case SLJIT_NEG_F64:
1964 FAIL_IF(push_inst(compiler, FSGNJN_S | FMT(op) | FRD(dst_r) | FRS1(src) | FRS2(src)));
1965 break;
1966 case SLJIT_ABS_F64:
1967 FAIL_IF(push_inst(compiler, FSGNJX_S | FMT(op) | FRD(dst_r) | FRS1(src) | FRS2(src)));
1968 break;
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)));
1972 op ^= SLJIT_32;
1973 break;
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;
1988 CHECK_ERROR();
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);
2002 src1 = TMP_FREG1;
2003 } else
2004 flags |= SLOW_SRC1;
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);
2010 src2 = TMP_FREG2;
2011 } else
2012 flags |= SLOW_SRC2;
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));
2020 else {
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)
2031 src1 = TMP_FREG1;
2032 if (flags & SLOW_SRC2)
2033 src2 = TMP_FREG2;
2035 switch (GET_OPCODE(op)) {
2036 case SLJIT_ADD_F64:
2037 FAIL_IF(push_inst(compiler, FADD_S | FMT(op) | FRD(dst_r) | FRS1(src1) | FRS2(src2)));
2038 break;
2040 case SLJIT_SUB_F64:
2041 FAIL_IF(push_inst(compiler, FSUB_S | FMT(op) | FRD(dst_r) | FRS1(src1) | FRS2(src2)));
2042 break;
2044 case SLJIT_MUL_F64:
2045 FAIL_IF(push_inst(compiler, FMUL_S | FMT(op) | FRD(dst_r) | FRS1(src1) | FRS2(src2)));
2046 break;
2048 case SLJIT_DIV_F64:
2049 FAIL_IF(push_inst(compiler, FDIV_S | FMT(op) | FRD(dst_r) | FRS1(src1) | FRS2(src2)));
2050 break;
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;
2059 #undef FLOAT_DATA
2060 #undef FMT
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)
2068 CHECK_ERROR();
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));
2075 /* Memory. */
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;
2087 CHECK_ERROR_PTR();
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);
2096 return label;
2099 #if (defined SLJIT_CONFIG_RISCV_32 && SLJIT_CONFIG_RISCV_32)
2100 #define BRANCH_LENGTH ((sljit_ins)(3 * sizeof(sljit_ins)) << 7)
2101 #else
2102 #define BRANCH_LENGTH ((sljit_ins)(7 * sizeof(sljit_ins)) << 7)
2103 #endif
2105 SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_jump(struct sljit_compiler *compiler, sljit_s32 type)
2107 struct sljit_jump *jump;
2108 sljit_ins inst;
2110 CHECK_ERROR_PTR();
2111 CHECK_PTR(check_sljit_emit_jump(compiler, type));
2113 jump = (struct sljit_jump*)ensure_abuf(compiler, sizeof(struct sljit_jump));
2114 PTR_FAIL_IF(!jump);
2115 set_jump(jump, compiler, type & SLJIT_REWRITABLE_JUMP);
2116 type &= 0xff;
2118 switch (type) {
2119 case SLJIT_EQUAL:
2120 inst = BNE | RS1(EQUAL_FLAG) | RS2(TMP_ZERO) | BRANCH_LENGTH;
2121 break;
2122 case SLJIT_NOT_EQUAL:
2123 inst = BEQ | RS1(EQUAL_FLAG) | RS2(TMP_ZERO) | BRANCH_LENGTH;
2124 break;
2125 case SLJIT_LESS:
2126 case SLJIT_GREATER:
2127 case SLJIT_SIG_LESS:
2128 case SLJIT_SIG_GREATER:
2129 case SLJIT_OVERFLOW:
2130 case SLJIT_CARRY:
2131 case SLJIT_F_EQUAL:
2132 case SLJIT_ORDERED_EQUAL:
2133 case SLJIT_ORDERED_NOT_EQUAL: /* Not supported. */
2134 case SLJIT_F_LESS:
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:
2140 case SLJIT_ORDERED:
2141 inst = BEQ | RS1(OTHER_FLAG) | RS2(TMP_ZERO) | BRANCH_LENGTH;
2142 break;
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;
2160 break;
2161 default:
2162 /* Not conditional branch. */
2163 inst = 0;
2164 break;
2167 if (inst != 0) {
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;
2185 #else
2186 compiler->size += 5;
2187 #endif
2188 return jump;
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);
2195 CHECK_ERROR_PTR();
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;
2212 sljit_s32 flags;
2213 sljit_ins inst;
2215 CHECK_ERROR_PTR();
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));
2230 src1 = TMP_REG1;
2233 if (src2 & SLJIT_MEM) {
2234 PTR_FAIL_IF(emit_op_mem2(compiler, flags, TMP_REG2, src2, src2w, 0, 0));
2235 src2 = TMP_REG2;
2238 if (src1 & SLJIT_IMM) {
2239 if (src1w != 0) {
2240 PTR_FAIL_IF(load_immediate(compiler, TMP_REG1, src1w, TMP_REG3));
2241 src1 = TMP_REG1;
2243 else
2244 src1 = TMP_ZERO;
2247 if (src2 & SLJIT_IMM) {
2248 if (src2w != 0) {
2249 PTR_FAIL_IF(load_immediate(compiler, TMP_REG2, src2w, TMP_REG3));
2250 src2 = TMP_REG2;
2252 else
2253 src2 = TMP_ZERO;
2256 jump = (struct sljit_jump*)ensure_abuf(compiler, sizeof(struct sljit_jump));
2257 PTR_FAIL_IF(!jump);
2258 set_jump(jump, compiler, (sljit_u32)((type & SLJIT_REWRITABLE_JUMP) | IS_COND));
2259 type &= 0xff;
2261 switch (type) {
2262 case SLJIT_EQUAL:
2263 inst = BNE | RS1(src1) | RS2(src2) | BRANCH_LENGTH;
2264 break;
2265 case SLJIT_NOT_EQUAL:
2266 inst = BEQ | RS1(src1) | RS2(src2) | BRANCH_LENGTH;
2267 break;
2268 case SLJIT_LESS:
2269 inst = BGEU | RS1(src1) | RS2(src2) | BRANCH_LENGTH;
2270 break;
2271 case SLJIT_GREATER_EQUAL:
2272 inst = BLTU | RS1(src1) | RS2(src2) | BRANCH_LENGTH;
2273 break;
2274 case SLJIT_GREATER:
2275 inst = BGEU | RS1(src2) | RS2(src1) | BRANCH_LENGTH;
2276 break;
2277 case SLJIT_LESS_EQUAL:
2278 inst = BLTU | RS1(src2) | RS2(src1) | BRANCH_LENGTH;
2279 break;
2280 case SLJIT_SIG_LESS:
2281 inst = BGE | RS1(src1) | RS2(src2) | BRANCH_LENGTH;
2282 break;
2283 case SLJIT_SIG_GREATER_EQUAL:
2284 inst = BLT | RS1(src1) | RS2(src2) | BRANCH_LENGTH;
2285 break;
2286 case SLJIT_SIG_GREATER:
2287 inst = BGE | RS1(src2) | RS2(src1) | BRANCH_LENGTH;
2288 break;
2289 case SLJIT_SIG_LESS_EQUAL:
2290 inst = BLT | RS1(src2) | RS2(src1) | BRANCH_LENGTH;
2291 break;
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;
2302 #else
2303 compiler->size += 5;
2304 #endif
2305 return jump;
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;
2314 CHECK_ERROR();
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));
2321 src = TMP_REG1;
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));
2328 FAIL_IF(!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;
2338 #else
2339 compiler->size += 5;
2340 #endif
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);
2349 CHECK_ERROR();
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));
2355 src = TMP_REG1;
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)));
2361 src = TMP_REG1;
2364 FAIL_IF(emit_stack_frame_release(compiler));
2365 type = SLJIT_JUMP;
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,
2374 sljit_s32 type)
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;
2380 #else
2381 sljit_s32 mem_type = ((op & SLJIT_32) || op == SLJIT_MOV32) ? (INT_DATA | SIGNED_DATA) : WORD_DATA;
2382 #endif
2384 CHECK_ERROR();
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) {
2398 src_r = OTHER_FLAG;
2399 invert = type & 0x1;
2401 switch (type) {
2402 case SLJIT_EQUAL:
2403 case SLJIT_NOT_EQUAL:
2404 FAIL_IF(push_inst(compiler, SLTUI | RD(dst_r) | RS1(EQUAL_FLAG) | IMM_I(1)));
2405 src_r = dst_r;
2406 break;
2407 case SLJIT_OVERFLOW:
2408 case SLJIT_NOT_OVERFLOW:
2409 if (compiler->status_flags_state & (SLJIT_CURRENT_FLAGS_ADD | SLJIT_CURRENT_FLAGS_SUB)) {
2410 src_r = OTHER_FLAG;
2411 break;
2413 FAIL_IF(push_inst(compiler, SLTUI | RD(dst_r) | RS1(OTHER_FLAG) | IMM_I(1)));
2414 src_r = dst_r;
2415 invert ^= 0x1;
2416 break;
2418 } else {
2419 invert = 0;
2420 src_r = OTHER_FLAG;
2422 switch (type) {
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:
2433 invert = 1;
2434 break;
2438 if (invert) {
2439 FAIL_IF(push_inst(compiler, XORI | RD(dst_r) | RS1(src_r) | IMM_I(1)));
2440 src_r = dst_r;
2443 if (op < SLJIT_ADD) {
2444 if (dst & SLJIT_MEM)
2445 return emit_op_mem(compiler, mem_type, src_r, dst, dstw);
2447 if (src_r != dst_r)
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,
2460 sljit_s32 dst_reg,
2461 sljit_s32 src, sljit_sw srcw)
2463 CHECK_ERROR();
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_;
2472 sljit_s32 dst_r;
2474 CHECK_ERROR_PTR();
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));
2488 return const_;
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;
2494 sljit_s32 dst_r;
2496 CHECK_ERROR_PTR();
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;
2508 #else
2509 compiler->size += 5;
2510 #endif
2512 if (dst & SLJIT_MEM)
2513 PTR_FAIL_IF(emit_op_mem(compiler, WORD_DATA, TMP_REG2, dst, dstw));
2515 return put_label;
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);