xref: /aosp_15_r20/external/pcre/src/sljit/sljitNativeRISCV_common.c (revision 22dc650d8ae982c6770746019a6f94af92b0f024)
1*22dc650dSSadaf Ebrahimi /*
2*22dc650dSSadaf Ebrahimi  *    Stack-less Just-In-Time compiler
3*22dc650dSSadaf Ebrahimi  *
4*22dc650dSSadaf Ebrahimi  *    Copyright Zoltan Herczeg ([email protected]). All rights reserved.
5*22dc650dSSadaf Ebrahimi  *
6*22dc650dSSadaf Ebrahimi  * Redistribution and use in source and binary forms, with or without modification, are
7*22dc650dSSadaf Ebrahimi  * permitted provided that the following conditions are met:
8*22dc650dSSadaf Ebrahimi  *
9*22dc650dSSadaf Ebrahimi  *   1. Redistributions of source code must retain the above copyright notice, this list of
10*22dc650dSSadaf Ebrahimi  *      conditions and the following disclaimer.
11*22dc650dSSadaf Ebrahimi  *
12*22dc650dSSadaf Ebrahimi  *   2. Redistributions in binary form must reproduce the above copyright notice, this list
13*22dc650dSSadaf Ebrahimi  *      of conditions and the following disclaimer in the documentation and/or other materials
14*22dc650dSSadaf Ebrahimi  *      provided with the distribution.
15*22dc650dSSadaf Ebrahimi  *
16*22dc650dSSadaf Ebrahimi  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) AND CONTRIBUTORS ``AS IS'' AND ANY
17*22dc650dSSadaf Ebrahimi  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
18*22dc650dSSadaf Ebrahimi  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
19*22dc650dSSadaf Ebrahimi  * SHALL THE COPYRIGHT HOLDER(S) OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
20*22dc650dSSadaf Ebrahimi  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
21*22dc650dSSadaf Ebrahimi  * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
22*22dc650dSSadaf Ebrahimi  * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
23*22dc650dSSadaf Ebrahimi  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
24*22dc650dSSadaf Ebrahimi  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25*22dc650dSSadaf Ebrahimi  */
26*22dc650dSSadaf Ebrahimi 
sljit_get_platform_name(void)27*22dc650dSSadaf Ebrahimi SLJIT_API_FUNC_ATTRIBUTE const char* sljit_get_platform_name(void)
28*22dc650dSSadaf Ebrahimi {
29*22dc650dSSadaf Ebrahimi #if (defined SLJIT_CONFIG_RISCV_32 && SLJIT_CONFIG_RISCV_32)
30*22dc650dSSadaf Ebrahimi 	return "RISC-V-32" SLJIT_CPUINFO;
31*22dc650dSSadaf Ebrahimi #else /* !SLJIT_CONFIG_RISCV_32 */
32*22dc650dSSadaf Ebrahimi 	return "RISC-V-64" SLJIT_CPUINFO;
33*22dc650dSSadaf Ebrahimi #endif /* SLJIT_CONFIG_RISCV_32 */
34*22dc650dSSadaf Ebrahimi }
35*22dc650dSSadaf Ebrahimi 
36*22dc650dSSadaf Ebrahimi /* Length of an instruction word
37*22dc650dSSadaf Ebrahimi    Both for riscv-32 and riscv-64 */
38*22dc650dSSadaf Ebrahimi typedef sljit_u32 sljit_ins;
39*22dc650dSSadaf Ebrahimi 
40*22dc650dSSadaf Ebrahimi #define TMP_REG1	(SLJIT_NUMBER_OF_REGISTERS + 2)
41*22dc650dSSadaf Ebrahimi #define TMP_REG2	(SLJIT_NUMBER_OF_REGISTERS + 3)
42*22dc650dSSadaf Ebrahimi #define TMP_REG3	(SLJIT_NUMBER_OF_REGISTERS + 4)
43*22dc650dSSadaf Ebrahimi #define TMP_ZERO	0
44*22dc650dSSadaf Ebrahimi 
45*22dc650dSSadaf Ebrahimi /* Flags are kept in volatile registers. */
46*22dc650dSSadaf Ebrahimi #define EQUAL_FLAG	(SLJIT_NUMBER_OF_REGISTERS + 5)
47*22dc650dSSadaf Ebrahimi #define RETURN_ADDR_REG	TMP_REG2
48*22dc650dSSadaf Ebrahimi #define OTHER_FLAG	(SLJIT_NUMBER_OF_REGISTERS + 6)
49*22dc650dSSadaf Ebrahimi 
50*22dc650dSSadaf Ebrahimi #define TMP_FREG1	(SLJIT_NUMBER_OF_FLOAT_REGISTERS + 1)
51*22dc650dSSadaf Ebrahimi #define TMP_FREG2	(SLJIT_NUMBER_OF_FLOAT_REGISTERS + 2)
52*22dc650dSSadaf Ebrahimi 
53*22dc650dSSadaf Ebrahimi static const sljit_u8 reg_map[SLJIT_NUMBER_OF_REGISTERS + 7] = {
54*22dc650dSSadaf Ebrahimi 	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
55*22dc650dSSadaf Ebrahimi };
56*22dc650dSSadaf Ebrahimi 
57*22dc650dSSadaf Ebrahimi static const sljit_u8 freg_map[SLJIT_NUMBER_OF_FLOAT_REGISTERS + 3] = {
58*22dc650dSSadaf Ebrahimi 	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,
59*22dc650dSSadaf Ebrahimi };
60*22dc650dSSadaf Ebrahimi 
61*22dc650dSSadaf Ebrahimi /* --------------------------------------------------------------------- */
62*22dc650dSSadaf Ebrahimi /*  Instrucion forms                                                     */
63*22dc650dSSadaf Ebrahimi /* --------------------------------------------------------------------- */
64*22dc650dSSadaf Ebrahimi 
65*22dc650dSSadaf Ebrahimi #define RD(rd)		((sljit_ins)reg_map[rd] << 7)
66*22dc650dSSadaf Ebrahimi #define RS1(rs1)	((sljit_ins)reg_map[rs1] << 15)
67*22dc650dSSadaf Ebrahimi #define RS2(rs2)	((sljit_ins)reg_map[rs2] << 20)
68*22dc650dSSadaf Ebrahimi #define FRD(rd)		((sljit_ins)freg_map[rd] << 7)
69*22dc650dSSadaf Ebrahimi #define FRS1(rs1)	((sljit_ins)freg_map[rs1] << 15)
70*22dc650dSSadaf Ebrahimi #define FRS2(rs2)	((sljit_ins)freg_map[rs2] << 20)
71*22dc650dSSadaf Ebrahimi #define IMM_I(imm)	((sljit_ins)(imm) << 20)
72*22dc650dSSadaf Ebrahimi #define IMM_S(imm)	((((sljit_ins)(imm) & 0xfe0) << 20) | (((sljit_ins)(imm) & 0x1f) << 7))
73*22dc650dSSadaf Ebrahimi 
74*22dc650dSSadaf Ebrahimi /* Represents funct(i) parts of the instructions. */
75*22dc650dSSadaf Ebrahimi #define OPC(o)		((sljit_ins)(o))
76*22dc650dSSadaf Ebrahimi #define F3(f)		((sljit_ins)(f) << 12)
77*22dc650dSSadaf Ebrahimi #define F12(f)		((sljit_ins)(f) << 20)
78*22dc650dSSadaf Ebrahimi #define F7(f)		((sljit_ins)(f) << 25)
79*22dc650dSSadaf Ebrahimi 
80*22dc650dSSadaf Ebrahimi #define ADD		(F7(0x0) | F3(0x0) | OPC(0x33))
81*22dc650dSSadaf Ebrahimi #define ADDI		(F3(0x0) | OPC(0x13))
82*22dc650dSSadaf Ebrahimi #define AND		(F7(0x0) | F3(0x7) | OPC(0x33))
83*22dc650dSSadaf Ebrahimi #define ANDI		(F3(0x7) | OPC(0x13))
84*22dc650dSSadaf Ebrahimi #define AUIPC		(OPC(0x17))
85*22dc650dSSadaf Ebrahimi #define BEQ		(F3(0x0) | OPC(0x63))
86*22dc650dSSadaf Ebrahimi #define BNE		(F3(0x1) | OPC(0x63))
87*22dc650dSSadaf Ebrahimi #define BLT		(F3(0x4) | OPC(0x63))
88*22dc650dSSadaf Ebrahimi #define BGE		(F3(0x5) | OPC(0x63))
89*22dc650dSSadaf Ebrahimi #define BLTU		(F3(0x6) | OPC(0x63))
90*22dc650dSSadaf Ebrahimi #define BGEU		(F3(0x7) | OPC(0x63))
91*22dc650dSSadaf Ebrahimi #define DIV		(F7(0x1) | F3(0x4) | OPC(0x33))
92*22dc650dSSadaf Ebrahimi #define DIVU		(F7(0x1) | F3(0x5) | OPC(0x33))
93*22dc650dSSadaf Ebrahimi #define EBREAK		(F12(0x1) | F3(0x0) | OPC(0x73))
94*22dc650dSSadaf Ebrahimi #define FADD_S		(F7(0x0) | F3(0x7) | OPC(0x53))
95*22dc650dSSadaf Ebrahimi #define FDIV_S		(F7(0xc) | F3(0x7) | OPC(0x53))
96*22dc650dSSadaf Ebrahimi #define FEQ_S		(F7(0x50) | F3(0x2) | OPC(0x53))
97*22dc650dSSadaf Ebrahimi #define FLD		(F3(0x3) | OPC(0x7))
98*22dc650dSSadaf Ebrahimi #define FLE_S		(F7(0x50) | F3(0x0) | OPC(0x53))
99*22dc650dSSadaf Ebrahimi #define FLT_S		(F7(0x50) | F3(0x1) | OPC(0x53))
100*22dc650dSSadaf Ebrahimi /* These conversion opcodes are partly defined. */
101*22dc650dSSadaf Ebrahimi #define FCVT_S_D	(F7(0x20) | OPC(0x53))
102*22dc650dSSadaf Ebrahimi #define FCVT_S_W	(F7(0x68) | OPC(0x53))
103*22dc650dSSadaf Ebrahimi #define FCVT_S_WU	(F7(0x68) | F12(0x1) | OPC(0x53))
104*22dc650dSSadaf Ebrahimi #define FCVT_W_S	(F7(0x60) | F3(0x1) | OPC(0x53))
105*22dc650dSSadaf Ebrahimi #define FMUL_S		(F7(0x8) | F3(0x7) | OPC(0x53))
106*22dc650dSSadaf Ebrahimi #define FMV_X_W		(F7(0x70) | F3(0x0) | OPC(0x53))
107*22dc650dSSadaf Ebrahimi #define FMV_W_X		(F7(0x78) | F3(0x0) | OPC(0x53))
108*22dc650dSSadaf Ebrahimi #define FSD		(F3(0x3) | OPC(0x27))
109*22dc650dSSadaf Ebrahimi #define FSGNJ_S		(F7(0x10) | F3(0x0) | OPC(0x53))
110*22dc650dSSadaf Ebrahimi #define FSGNJN_S	(F7(0x10) | F3(0x1) | OPC(0x53))
111*22dc650dSSadaf Ebrahimi #define FSGNJX_S	(F7(0x10) | F3(0x2) | OPC(0x53))
112*22dc650dSSadaf Ebrahimi #define FSUB_S		(F7(0x4) | F3(0x7) | OPC(0x53))
113*22dc650dSSadaf Ebrahimi #define FSW		(F3(0x2) | OPC(0x27))
114*22dc650dSSadaf Ebrahimi #define JAL		(OPC(0x6f))
115*22dc650dSSadaf Ebrahimi #define JALR		(F3(0x0) | OPC(0x67))
116*22dc650dSSadaf Ebrahimi #define LD		(F3(0x3) | OPC(0x3))
117*22dc650dSSadaf Ebrahimi #define LUI		(OPC(0x37))
118*22dc650dSSadaf Ebrahimi #define LW		(F3(0x2) | OPC(0x3))
119*22dc650dSSadaf Ebrahimi #define MUL		(F7(0x1) | F3(0x0) | OPC(0x33))
120*22dc650dSSadaf Ebrahimi #define MULH		(F7(0x1) | F3(0x1) | OPC(0x33))
121*22dc650dSSadaf Ebrahimi #define MULHU		(F7(0x1) | F3(0x3) | OPC(0x33))
122*22dc650dSSadaf Ebrahimi #define OR		(F7(0x0) | F3(0x6) | OPC(0x33))
123*22dc650dSSadaf Ebrahimi #define ORI		(F3(0x6) | OPC(0x13))
124*22dc650dSSadaf Ebrahimi #define REM		(F7(0x1) | F3(0x6) | OPC(0x33))
125*22dc650dSSadaf Ebrahimi #define REMU		(F7(0x1) | F3(0x7) | OPC(0x33))
126*22dc650dSSadaf Ebrahimi #define SD		(F3(0x3) | OPC(0x23))
127*22dc650dSSadaf Ebrahimi #define SLL		(F7(0x0) | F3(0x1) | OPC(0x33))
128*22dc650dSSadaf Ebrahimi #define SLLI		(IMM_I(0x0) | F3(0x1) | OPC(0x13))
129*22dc650dSSadaf Ebrahimi #define SLT		(F7(0x0) | F3(0x2) | OPC(0x33))
130*22dc650dSSadaf Ebrahimi #define SLTI		(F3(0x2) | OPC(0x13))
131*22dc650dSSadaf Ebrahimi #define SLTU		(F7(0x0) | F3(0x3) | OPC(0x33))
132*22dc650dSSadaf Ebrahimi #define SLTUI		(F3(0x3) | OPC(0x13))
133*22dc650dSSadaf Ebrahimi #define SRL		(F7(0x0) | F3(0x5) | OPC(0x33))
134*22dc650dSSadaf Ebrahimi #define SRLI		(IMM_I(0x0) | F3(0x5) | OPC(0x13))
135*22dc650dSSadaf Ebrahimi #define SRA		(F7(0x20) | F3(0x5) | OPC(0x33))
136*22dc650dSSadaf Ebrahimi #define SRAI		(IMM_I(0x400) | F3(0x5) | OPC(0x13))
137*22dc650dSSadaf Ebrahimi #define SUB		(F7(0x20) | F3(0x0) | OPC(0x33))
138*22dc650dSSadaf Ebrahimi #define SW		(F3(0x2) | OPC(0x23))
139*22dc650dSSadaf Ebrahimi #define XOR		(F7(0x0) | F3(0x4) | OPC(0x33))
140*22dc650dSSadaf Ebrahimi #define XORI		(F3(0x4) | OPC(0x13))
141*22dc650dSSadaf Ebrahimi 
142*22dc650dSSadaf Ebrahimi #define SIMM_MAX	(0x7ff)
143*22dc650dSSadaf Ebrahimi #define SIMM_MIN	(-0x800)
144*22dc650dSSadaf Ebrahimi #define BRANCH_MAX	(0xfff)
145*22dc650dSSadaf Ebrahimi #define BRANCH_MIN	(-0x1000)
146*22dc650dSSadaf Ebrahimi #define JUMP_MAX	(0xfffff)
147*22dc650dSSadaf Ebrahimi #define JUMP_MIN	(-0x100000)
148*22dc650dSSadaf Ebrahimi 
149*22dc650dSSadaf Ebrahimi #if (defined SLJIT_CONFIG_RISCV_64 && SLJIT_CONFIG_RISCV_64)
150*22dc650dSSadaf Ebrahimi #define S32_MAX		(0x7ffff7ffl)
151*22dc650dSSadaf Ebrahimi #define S32_MIN		(-0x80000000l)
152*22dc650dSSadaf Ebrahimi #define S44_MAX		(0x7fffffff7ffl)
153*22dc650dSSadaf Ebrahimi #define S52_MAX		(0x7ffffffffffffl)
154*22dc650dSSadaf Ebrahimi #endif
155*22dc650dSSadaf Ebrahimi 
push_inst(struct sljit_compiler * compiler,sljit_ins ins)156*22dc650dSSadaf Ebrahimi static sljit_s32 push_inst(struct sljit_compiler *compiler, sljit_ins ins)
157*22dc650dSSadaf Ebrahimi {
158*22dc650dSSadaf Ebrahimi 	sljit_ins *ptr = (sljit_ins*)ensure_buf(compiler, sizeof(sljit_ins));
159*22dc650dSSadaf Ebrahimi 	FAIL_IF(!ptr);
160*22dc650dSSadaf Ebrahimi 	*ptr = ins;
161*22dc650dSSadaf Ebrahimi 	compiler->size++;
162*22dc650dSSadaf Ebrahimi 	return SLJIT_SUCCESS;
163*22dc650dSSadaf Ebrahimi }
164*22dc650dSSadaf Ebrahimi 
push_imm_s_inst(struct sljit_compiler * compiler,sljit_ins ins,sljit_sw imm)165*22dc650dSSadaf Ebrahimi static sljit_s32 push_imm_s_inst(struct sljit_compiler *compiler, sljit_ins ins, sljit_sw imm)
166*22dc650dSSadaf Ebrahimi {
167*22dc650dSSadaf Ebrahimi 	return push_inst(compiler, ins | IMM_S(imm));
168*22dc650dSSadaf Ebrahimi }
169*22dc650dSSadaf Ebrahimi 
detect_jump_type(struct sljit_jump * jump,sljit_ins * code,sljit_sw executable_offset)170*22dc650dSSadaf Ebrahimi static SLJIT_INLINE sljit_ins* detect_jump_type(struct sljit_jump *jump, sljit_ins *code, sljit_sw executable_offset)
171*22dc650dSSadaf Ebrahimi {
172*22dc650dSSadaf Ebrahimi 	sljit_sw diff;
173*22dc650dSSadaf Ebrahimi 	sljit_uw target_addr;
174*22dc650dSSadaf Ebrahimi 	sljit_ins *inst;
175*22dc650dSSadaf Ebrahimi 
176*22dc650dSSadaf Ebrahimi 	inst = (sljit_ins *)jump->addr;
177*22dc650dSSadaf Ebrahimi 
178*22dc650dSSadaf Ebrahimi 	if (jump->flags & SLJIT_REWRITABLE_JUMP)
179*22dc650dSSadaf Ebrahimi 		goto exit;
180*22dc650dSSadaf Ebrahimi 
181*22dc650dSSadaf Ebrahimi 	if (jump->flags & JUMP_ADDR)
182*22dc650dSSadaf Ebrahimi 		target_addr = jump->u.target;
183*22dc650dSSadaf Ebrahimi 	else {
184*22dc650dSSadaf Ebrahimi 		SLJIT_ASSERT(jump->u.label != NULL);
185*22dc650dSSadaf Ebrahimi 		target_addr = (sljit_uw)(code + jump->u.label->size) + (sljit_uw)executable_offset;
186*22dc650dSSadaf Ebrahimi 	}
187*22dc650dSSadaf Ebrahimi 
188*22dc650dSSadaf Ebrahimi 	diff = (sljit_sw)target_addr - (sljit_sw)inst - executable_offset;
189*22dc650dSSadaf Ebrahimi 
190*22dc650dSSadaf Ebrahimi 	if (jump->flags & IS_COND) {
191*22dc650dSSadaf Ebrahimi 		diff += SSIZE_OF(ins);
192*22dc650dSSadaf Ebrahimi 
193*22dc650dSSadaf Ebrahimi 		if (diff >= BRANCH_MIN && diff <= BRANCH_MAX) {
194*22dc650dSSadaf Ebrahimi 			inst--;
195*22dc650dSSadaf Ebrahimi 			inst[0] = (inst[0] & 0x1fff07f) ^ 0x1000;
196*22dc650dSSadaf Ebrahimi 			jump->flags |= PATCH_B;
197*22dc650dSSadaf Ebrahimi 			jump->addr = (sljit_uw)inst;
198*22dc650dSSadaf Ebrahimi 			return inst;
199*22dc650dSSadaf Ebrahimi 		}
200*22dc650dSSadaf Ebrahimi 
201*22dc650dSSadaf Ebrahimi 		diff -= SSIZE_OF(ins);
202*22dc650dSSadaf Ebrahimi 	}
203*22dc650dSSadaf Ebrahimi 
204*22dc650dSSadaf Ebrahimi 	if (diff >= JUMP_MIN && diff <= JUMP_MAX) {
205*22dc650dSSadaf Ebrahimi 		if (jump->flags & IS_COND) {
206*22dc650dSSadaf Ebrahimi #if (defined SLJIT_CONFIG_RISCV_32 && SLJIT_CONFIG_RISCV_32)
207*22dc650dSSadaf Ebrahimi 			inst[-1] -= (sljit_ins)(1 * sizeof(sljit_ins)) << 7;
208*22dc650dSSadaf Ebrahimi #else
209*22dc650dSSadaf Ebrahimi 			inst[-1] -= (sljit_ins)(5 * sizeof(sljit_ins)) << 7;
210*22dc650dSSadaf Ebrahimi #endif
211*22dc650dSSadaf Ebrahimi 		}
212*22dc650dSSadaf Ebrahimi 
213*22dc650dSSadaf Ebrahimi 		jump->flags |= PATCH_J;
214*22dc650dSSadaf Ebrahimi 		return inst;
215*22dc650dSSadaf Ebrahimi 	}
216*22dc650dSSadaf Ebrahimi 
217*22dc650dSSadaf Ebrahimi #if (defined SLJIT_CONFIG_RISCV_64 && SLJIT_CONFIG_RISCV_64)
218*22dc650dSSadaf Ebrahimi 	if (diff >= S32_MIN && diff <= S32_MAX) {
219*22dc650dSSadaf Ebrahimi 		if (jump->flags & IS_COND)
220*22dc650dSSadaf Ebrahimi 			inst[-1] -= (sljit_ins)(4 * sizeof(sljit_ins)) << 7;
221*22dc650dSSadaf Ebrahimi 
222*22dc650dSSadaf Ebrahimi 		jump->flags |= PATCH_REL32;
223*22dc650dSSadaf Ebrahimi 		inst[1] = inst[0];
224*22dc650dSSadaf Ebrahimi 		return inst + 1;
225*22dc650dSSadaf Ebrahimi 	}
226*22dc650dSSadaf Ebrahimi 
227*22dc650dSSadaf Ebrahimi 	if (target_addr <= (sljit_uw)S32_MAX) {
228*22dc650dSSadaf Ebrahimi 		if (jump->flags & IS_COND)
229*22dc650dSSadaf Ebrahimi 			inst[-1] -= (sljit_ins)(4 * sizeof(sljit_ins)) << 7;
230*22dc650dSSadaf Ebrahimi 
231*22dc650dSSadaf Ebrahimi 		jump->flags |= PATCH_ABS32;
232*22dc650dSSadaf Ebrahimi 		inst[1] = inst[0];
233*22dc650dSSadaf Ebrahimi 		return inst + 1;
234*22dc650dSSadaf Ebrahimi 	}
235*22dc650dSSadaf Ebrahimi 
236*22dc650dSSadaf Ebrahimi 	if (target_addr <= S44_MAX) {
237*22dc650dSSadaf Ebrahimi 		if (jump->flags & IS_COND)
238*22dc650dSSadaf Ebrahimi 			inst[-1] -= (sljit_ins)(2 * sizeof(sljit_ins)) << 7;
239*22dc650dSSadaf Ebrahimi 
240*22dc650dSSadaf Ebrahimi 		jump->flags |= PATCH_ABS44;
241*22dc650dSSadaf Ebrahimi 		inst[3] = inst[0];
242*22dc650dSSadaf Ebrahimi 		return inst + 3;
243*22dc650dSSadaf Ebrahimi 	}
244*22dc650dSSadaf Ebrahimi 
245*22dc650dSSadaf Ebrahimi 	if (target_addr <= S52_MAX) {
246*22dc650dSSadaf Ebrahimi 		if (jump->flags & IS_COND)
247*22dc650dSSadaf Ebrahimi 			inst[-1] -= (sljit_ins)(1 * sizeof(sljit_ins)) << 7;
248*22dc650dSSadaf Ebrahimi 
249*22dc650dSSadaf Ebrahimi 		jump->flags |= PATCH_ABS52;
250*22dc650dSSadaf Ebrahimi 		inst[4] = inst[0];
251*22dc650dSSadaf Ebrahimi 		return inst + 4;
252*22dc650dSSadaf Ebrahimi 	}
253*22dc650dSSadaf Ebrahimi #endif
254*22dc650dSSadaf Ebrahimi 
255*22dc650dSSadaf Ebrahimi exit:
256*22dc650dSSadaf Ebrahimi #if (defined SLJIT_CONFIG_RISCV_32 && SLJIT_CONFIG_RISCV_32)
257*22dc650dSSadaf Ebrahimi 	inst[1] = inst[0];
258*22dc650dSSadaf Ebrahimi 	return inst + 1;
259*22dc650dSSadaf Ebrahimi #else
260*22dc650dSSadaf Ebrahimi 	inst[5] = inst[0];
261*22dc650dSSadaf Ebrahimi 	return inst + 5;
262*22dc650dSSadaf Ebrahimi #endif
263*22dc650dSSadaf Ebrahimi }
264*22dc650dSSadaf Ebrahimi 
265*22dc650dSSadaf Ebrahimi #if (defined SLJIT_CONFIG_RISCV_64 && SLJIT_CONFIG_RISCV_64)
266*22dc650dSSadaf Ebrahimi 
mov_addr_get_length(struct sljit_jump * jump,sljit_ins * code_ptr,sljit_ins * code,sljit_sw executable_offset)267*22dc650dSSadaf Ebrahimi static SLJIT_INLINE sljit_sw mov_addr_get_length(struct sljit_jump *jump, sljit_ins *code_ptr, sljit_ins *code, sljit_sw executable_offset)
268*22dc650dSSadaf Ebrahimi {
269*22dc650dSSadaf Ebrahimi 	sljit_uw addr;
270*22dc650dSSadaf Ebrahimi 	sljit_sw diff;
271*22dc650dSSadaf Ebrahimi 	SLJIT_UNUSED_ARG(executable_offset);
272*22dc650dSSadaf Ebrahimi 
273*22dc650dSSadaf Ebrahimi 	SLJIT_ASSERT(jump->flags < ((sljit_uw)6 << JUMP_SIZE_SHIFT));
274*22dc650dSSadaf Ebrahimi 	if (jump->flags & JUMP_ADDR)
275*22dc650dSSadaf Ebrahimi 		addr = jump->u.target;
276*22dc650dSSadaf Ebrahimi 	else
277*22dc650dSSadaf Ebrahimi 		addr = (sljit_uw)SLJIT_ADD_EXEC_OFFSET(code + jump->u.label->size, executable_offset);
278*22dc650dSSadaf Ebrahimi 
279*22dc650dSSadaf Ebrahimi 	diff = (sljit_sw)addr - (sljit_sw)SLJIT_ADD_EXEC_OFFSET(code_ptr, executable_offset);
280*22dc650dSSadaf Ebrahimi 
281*22dc650dSSadaf Ebrahimi 	if (diff >= S32_MIN && diff <= S32_MAX) {
282*22dc650dSSadaf Ebrahimi 		SLJIT_ASSERT(jump->flags >= ((sljit_uw)1 << JUMP_SIZE_SHIFT));
283*22dc650dSSadaf Ebrahimi 		jump->flags |= PATCH_REL32;
284*22dc650dSSadaf Ebrahimi 		return 1;
285*22dc650dSSadaf Ebrahimi 	}
286*22dc650dSSadaf Ebrahimi 
287*22dc650dSSadaf Ebrahimi 	if (addr <= S32_MAX) {
288*22dc650dSSadaf Ebrahimi 		SLJIT_ASSERT(jump->flags >= ((sljit_uw)1 << JUMP_SIZE_SHIFT));
289*22dc650dSSadaf Ebrahimi 		jump->flags |= PATCH_ABS32;
290*22dc650dSSadaf Ebrahimi 		return 1;
291*22dc650dSSadaf Ebrahimi 	}
292*22dc650dSSadaf Ebrahimi 
293*22dc650dSSadaf Ebrahimi 	if (addr <= S44_MAX) {
294*22dc650dSSadaf Ebrahimi 		SLJIT_ASSERT(jump->flags >= ((sljit_uw)3 << JUMP_SIZE_SHIFT));
295*22dc650dSSadaf Ebrahimi 		jump->flags |= PATCH_ABS44;
296*22dc650dSSadaf Ebrahimi 		return 3;
297*22dc650dSSadaf Ebrahimi 	}
298*22dc650dSSadaf Ebrahimi 
299*22dc650dSSadaf Ebrahimi 	if (addr <= S52_MAX) {
300*22dc650dSSadaf Ebrahimi 		SLJIT_ASSERT(jump->flags >= ((sljit_uw)4 << JUMP_SIZE_SHIFT));
301*22dc650dSSadaf Ebrahimi 		jump->flags |= PATCH_ABS52;
302*22dc650dSSadaf Ebrahimi 		return 4;
303*22dc650dSSadaf Ebrahimi 	}
304*22dc650dSSadaf Ebrahimi 
305*22dc650dSSadaf Ebrahimi 	SLJIT_ASSERT(jump->flags >= ((sljit_uw)5 << JUMP_SIZE_SHIFT));
306*22dc650dSSadaf Ebrahimi 	return 5;
307*22dc650dSSadaf Ebrahimi }
308*22dc650dSSadaf Ebrahimi 
309*22dc650dSSadaf Ebrahimi #endif /* SLJIT_CONFIG_RISCV_64 */
310*22dc650dSSadaf Ebrahimi 
load_addr_to_reg(struct sljit_jump * jump,sljit_sw executable_offset)311*22dc650dSSadaf Ebrahimi static SLJIT_INLINE void load_addr_to_reg(struct sljit_jump *jump, sljit_sw executable_offset)
312*22dc650dSSadaf Ebrahimi {
313*22dc650dSSadaf Ebrahimi 	sljit_uw flags = jump->flags;
314*22dc650dSSadaf Ebrahimi 	sljit_uw addr = (flags & JUMP_ADDR) ? jump->u.target : jump->u.label->u.addr;
315*22dc650dSSadaf Ebrahimi 	sljit_ins *ins = (sljit_ins*)jump->addr;
316*22dc650dSSadaf Ebrahimi 	sljit_u32 reg = (flags & JUMP_MOV_ADDR) ? *ins : TMP_REG1;
317*22dc650dSSadaf Ebrahimi #if (defined SLJIT_CONFIG_RISCV_64 && SLJIT_CONFIG_RISCV_64)
318*22dc650dSSadaf Ebrahimi 	sljit_sw high;
319*22dc650dSSadaf Ebrahimi #endif
320*22dc650dSSadaf Ebrahimi 	SLJIT_UNUSED_ARG(executable_offset);
321*22dc650dSSadaf Ebrahimi 
322*22dc650dSSadaf Ebrahimi #if (defined SLJIT_CONFIG_RISCV_64 && SLJIT_CONFIG_RISCV_64)
323*22dc650dSSadaf Ebrahimi 	if (flags & PATCH_REL32) {
324*22dc650dSSadaf Ebrahimi 		addr -= (sljit_uw)SLJIT_ADD_EXEC_OFFSET(ins, executable_offset);
325*22dc650dSSadaf Ebrahimi 
326*22dc650dSSadaf Ebrahimi 		SLJIT_ASSERT((sljit_sw)addr >= S32_MIN && (sljit_sw)addr <= S32_MAX);
327*22dc650dSSadaf Ebrahimi 
328*22dc650dSSadaf Ebrahimi 		if ((addr & 0x800) != 0)
329*22dc650dSSadaf Ebrahimi 			addr += 0x1000;
330*22dc650dSSadaf Ebrahimi 
331*22dc650dSSadaf Ebrahimi 		ins[0] = AUIPC | RD(reg) | (sljit_ins)((sljit_sw)addr & ~0xfff);
332*22dc650dSSadaf Ebrahimi 
333*22dc650dSSadaf Ebrahimi 		if (!(flags & JUMP_MOV_ADDR)) {
334*22dc650dSSadaf Ebrahimi 			SLJIT_ASSERT((ins[1] & 0x707f) == JALR);
335*22dc650dSSadaf Ebrahimi 			ins[1] = (ins[1] & 0xfffff) | IMM_I(addr);
336*22dc650dSSadaf Ebrahimi 		} else
337*22dc650dSSadaf Ebrahimi 			ins[1] = ADDI | RD(reg) | RS1(reg) | IMM_I(addr);
338*22dc650dSSadaf Ebrahimi 		return;
339*22dc650dSSadaf Ebrahimi 	}
340*22dc650dSSadaf Ebrahimi #endif
341*22dc650dSSadaf Ebrahimi 
342*22dc650dSSadaf Ebrahimi 	if ((addr & 0x800) != 0)
343*22dc650dSSadaf Ebrahimi 		addr += 0x1000;
344*22dc650dSSadaf Ebrahimi 
345*22dc650dSSadaf Ebrahimi #if (defined SLJIT_CONFIG_RISCV_32 && SLJIT_CONFIG_RISCV_32)
346*22dc650dSSadaf Ebrahimi 	ins[0] = LUI | RD(reg) | (sljit_ins)((sljit_sw)addr & ~0xfff);
347*22dc650dSSadaf Ebrahimi #else /* !SLJIT_CONFIG_RISCV_32 */
348*22dc650dSSadaf Ebrahimi 
349*22dc650dSSadaf Ebrahimi 	if (flags & PATCH_ABS32) {
350*22dc650dSSadaf Ebrahimi 		SLJIT_ASSERT(addr <= S32_MAX);
351*22dc650dSSadaf Ebrahimi 		ins[0] = LUI | RD(reg) | (sljit_ins)((sljit_sw)addr & ~0xfff);
352*22dc650dSSadaf Ebrahimi 	} else if (flags & PATCH_ABS44) {
353*22dc650dSSadaf Ebrahimi 		high = (sljit_sw)addr >> 12;
354*22dc650dSSadaf Ebrahimi 		SLJIT_ASSERT((sljit_uw)high <= 0x7fffffff);
355*22dc650dSSadaf Ebrahimi 
356*22dc650dSSadaf Ebrahimi 		if (high > S32_MAX) {
357*22dc650dSSadaf Ebrahimi 			SLJIT_ASSERT((high & 0x800) != 0);
358*22dc650dSSadaf Ebrahimi 			ins[0] = LUI | RD(reg) | (sljit_ins)0x80000000u;
359*22dc650dSSadaf Ebrahimi 			ins[1] = XORI | RD(reg) | RS1(reg) | IMM_I(high);
360*22dc650dSSadaf Ebrahimi 		} else {
361*22dc650dSSadaf Ebrahimi 			if ((high & 0x800) != 0)
362*22dc650dSSadaf Ebrahimi 				high += 0x1000;
363*22dc650dSSadaf Ebrahimi 
364*22dc650dSSadaf Ebrahimi 			ins[0] = LUI | RD(reg) | (sljit_ins)(high & ~0xfff);
365*22dc650dSSadaf Ebrahimi 			ins[1] = ADDI | RD(reg) | RS1(reg) | IMM_I(high);
366*22dc650dSSadaf Ebrahimi 		}
367*22dc650dSSadaf Ebrahimi 
368*22dc650dSSadaf Ebrahimi 		ins[2] = SLLI | RD(reg) | RS1(reg) | IMM_I(12);
369*22dc650dSSadaf Ebrahimi 		ins += 2;
370*22dc650dSSadaf Ebrahimi 	} else {
371*22dc650dSSadaf Ebrahimi 		high = (sljit_sw)addr >> 32;
372*22dc650dSSadaf Ebrahimi 
373*22dc650dSSadaf Ebrahimi 		if ((addr & 0x80000000l) != 0)
374*22dc650dSSadaf Ebrahimi 			high = ~high;
375*22dc650dSSadaf Ebrahimi 
376*22dc650dSSadaf Ebrahimi 		if (flags & PATCH_ABS52) {
377*22dc650dSSadaf Ebrahimi 			SLJIT_ASSERT(addr <= S52_MAX);
378*22dc650dSSadaf Ebrahimi 			ins[0] = LUI | RD(TMP_REG3) | (sljit_ins)(high << 12);
379*22dc650dSSadaf Ebrahimi 		} else {
380*22dc650dSSadaf Ebrahimi 			if ((high & 0x800) != 0)
381*22dc650dSSadaf Ebrahimi 				high += 0x1000;
382*22dc650dSSadaf Ebrahimi 			ins[0] = LUI | RD(TMP_REG3) | (sljit_ins)(high & ~0xfff);
383*22dc650dSSadaf Ebrahimi 			ins[1] = ADDI | RD(TMP_REG3) | RS1(TMP_REG3) | IMM_I(high);
384*22dc650dSSadaf Ebrahimi 			ins++;
385*22dc650dSSadaf Ebrahimi 		}
386*22dc650dSSadaf Ebrahimi 
387*22dc650dSSadaf Ebrahimi 		ins[1] = LUI | RD(reg) | (sljit_ins)((sljit_sw)addr & ~0xfff);
388*22dc650dSSadaf Ebrahimi 		ins[2] = SLLI | RD(TMP_REG3) | RS1(TMP_REG3) | IMM_I((flags & PATCH_ABS52) ? 20 : 32);
389*22dc650dSSadaf Ebrahimi 		ins[3] = XOR | RD(reg) | RS1(reg) | RS2(TMP_REG3);
390*22dc650dSSadaf Ebrahimi 		ins += 3;
391*22dc650dSSadaf Ebrahimi 	}
392*22dc650dSSadaf Ebrahimi #endif /* !SLJIT_CONFIG_RISCV_32 */
393*22dc650dSSadaf Ebrahimi 
394*22dc650dSSadaf Ebrahimi 	if (!(flags & JUMP_MOV_ADDR)) {
395*22dc650dSSadaf Ebrahimi 		SLJIT_ASSERT((ins[1] & 0x707f) == JALR);
396*22dc650dSSadaf Ebrahimi 		ins[1] = (ins[1] & 0xfffff) | IMM_I(addr);
397*22dc650dSSadaf Ebrahimi 	} else
398*22dc650dSSadaf Ebrahimi 		ins[1] = ADDI | RD(reg) | RS1(reg) | IMM_I(addr);
399*22dc650dSSadaf Ebrahimi }
400*22dc650dSSadaf Ebrahimi 
reduce_code_size(struct sljit_compiler * compiler)401*22dc650dSSadaf Ebrahimi static void reduce_code_size(struct sljit_compiler *compiler)
402*22dc650dSSadaf Ebrahimi {
403*22dc650dSSadaf Ebrahimi 	struct sljit_label *label;
404*22dc650dSSadaf Ebrahimi 	struct sljit_jump *jump;
405*22dc650dSSadaf Ebrahimi 	struct sljit_const *const_;
406*22dc650dSSadaf Ebrahimi 	SLJIT_NEXT_DEFINE_TYPES;
407*22dc650dSSadaf Ebrahimi 	sljit_uw total_size;
408*22dc650dSSadaf Ebrahimi 	sljit_uw size_reduce = 0;
409*22dc650dSSadaf Ebrahimi 	sljit_sw diff;
410*22dc650dSSadaf Ebrahimi 
411*22dc650dSSadaf Ebrahimi 	label = compiler->labels;
412*22dc650dSSadaf Ebrahimi 	jump = compiler->jumps;
413*22dc650dSSadaf Ebrahimi 	const_ = compiler->consts;
414*22dc650dSSadaf Ebrahimi 	SLJIT_NEXT_INIT_TYPES();
415*22dc650dSSadaf Ebrahimi 
416*22dc650dSSadaf Ebrahimi 	while (1) {
417*22dc650dSSadaf Ebrahimi 		SLJIT_GET_NEXT_MIN();
418*22dc650dSSadaf Ebrahimi 
419*22dc650dSSadaf Ebrahimi 		if (next_min_addr == SLJIT_MAX_ADDRESS)
420*22dc650dSSadaf Ebrahimi 			break;
421*22dc650dSSadaf Ebrahimi 
422*22dc650dSSadaf Ebrahimi 		if (next_min_addr == next_label_size) {
423*22dc650dSSadaf Ebrahimi 			label->size -= size_reduce;
424*22dc650dSSadaf Ebrahimi 
425*22dc650dSSadaf Ebrahimi 			label = label->next;
426*22dc650dSSadaf Ebrahimi 			next_label_size = SLJIT_GET_NEXT_SIZE(label);
427*22dc650dSSadaf Ebrahimi 		}
428*22dc650dSSadaf Ebrahimi 
429*22dc650dSSadaf Ebrahimi 		if (next_min_addr == next_const_addr) {
430*22dc650dSSadaf Ebrahimi 			const_->addr -= size_reduce;
431*22dc650dSSadaf Ebrahimi 			const_ = const_->next;
432*22dc650dSSadaf Ebrahimi 			next_const_addr = SLJIT_GET_NEXT_ADDRESS(const_);
433*22dc650dSSadaf Ebrahimi 			continue;
434*22dc650dSSadaf Ebrahimi 		}
435*22dc650dSSadaf Ebrahimi 
436*22dc650dSSadaf Ebrahimi 		if (next_min_addr != next_jump_addr)
437*22dc650dSSadaf Ebrahimi 			continue;
438*22dc650dSSadaf Ebrahimi 
439*22dc650dSSadaf Ebrahimi 		jump->addr -= size_reduce;
440*22dc650dSSadaf Ebrahimi 		if (!(jump->flags & JUMP_MOV_ADDR)) {
441*22dc650dSSadaf Ebrahimi 			total_size = JUMP_MAX_SIZE;
442*22dc650dSSadaf Ebrahimi 
443*22dc650dSSadaf Ebrahimi 			if (!(jump->flags & SLJIT_REWRITABLE_JUMP)) {
444*22dc650dSSadaf Ebrahimi 				if (jump->flags & JUMP_ADDR) {
445*22dc650dSSadaf Ebrahimi #if (defined SLJIT_CONFIG_RISCV_64 && SLJIT_CONFIG_RISCV_64)
446*22dc650dSSadaf Ebrahimi 					if (jump->u.target <= S32_MAX)
447*22dc650dSSadaf Ebrahimi 						total_size = 2;
448*22dc650dSSadaf Ebrahimi 					else if (jump->u.target <= S44_MAX)
449*22dc650dSSadaf Ebrahimi 						total_size = 4;
450*22dc650dSSadaf Ebrahimi 					else if (jump->u.target <= S52_MAX)
451*22dc650dSSadaf Ebrahimi 						total_size = 5;
452*22dc650dSSadaf Ebrahimi #endif /* SLJIT_CONFIG_RISCV_64 */
453*22dc650dSSadaf Ebrahimi 				} else {
454*22dc650dSSadaf Ebrahimi 					/* Unit size: instruction. */
455*22dc650dSSadaf Ebrahimi 					diff = (sljit_sw)jump->u.label->size - (sljit_sw)jump->addr;
456*22dc650dSSadaf Ebrahimi 
457*22dc650dSSadaf Ebrahimi 					if ((jump->flags & IS_COND) && (diff + 1) <= (BRANCH_MAX / SSIZE_OF(ins)) && (diff + 1) >= (BRANCH_MIN / SSIZE_OF(ins)))
458*22dc650dSSadaf Ebrahimi 						total_size = 0;
459*22dc650dSSadaf Ebrahimi 					else if (diff >= (JUMP_MIN / SSIZE_OF(ins)) && diff <= (JUMP_MAX / SSIZE_OF(ins)))
460*22dc650dSSadaf Ebrahimi 						total_size = 1;
461*22dc650dSSadaf Ebrahimi #if (defined SLJIT_CONFIG_RISCV_64 && SLJIT_CONFIG_RISCV_64)
462*22dc650dSSadaf Ebrahimi 					else if (diff >= (S32_MIN / SSIZE_OF(ins)) && diff <= (S32_MAX / SSIZE_OF(ins)))
463*22dc650dSSadaf Ebrahimi 						total_size = 2;
464*22dc650dSSadaf Ebrahimi #endif /* SLJIT_CONFIG_RISCV_64 */
465*22dc650dSSadaf Ebrahimi 				}
466*22dc650dSSadaf Ebrahimi 			}
467*22dc650dSSadaf Ebrahimi 
468*22dc650dSSadaf Ebrahimi 			size_reduce += JUMP_MAX_SIZE - total_size;
469*22dc650dSSadaf Ebrahimi 			jump->flags |= total_size << JUMP_SIZE_SHIFT;
470*22dc650dSSadaf Ebrahimi #if (defined SLJIT_CONFIG_RISCV_64 && SLJIT_CONFIG_RISCV_64)
471*22dc650dSSadaf Ebrahimi 		} else {
472*22dc650dSSadaf Ebrahimi 			total_size = 5;
473*22dc650dSSadaf Ebrahimi 
474*22dc650dSSadaf Ebrahimi 			if (!(jump->flags & JUMP_ADDR)) {
475*22dc650dSSadaf Ebrahimi 				/* Real size minus 1. Unit size: instruction. */
476*22dc650dSSadaf Ebrahimi 				diff = (sljit_sw)jump->u.label->size - (sljit_sw)jump->addr;
477*22dc650dSSadaf Ebrahimi 
478*22dc650dSSadaf Ebrahimi 				if (diff >= (S32_MIN / SSIZE_OF(ins)) && diff <= (S32_MAX / SSIZE_OF(ins)))
479*22dc650dSSadaf Ebrahimi 					total_size = 1;
480*22dc650dSSadaf Ebrahimi 			} else if (jump->u.target < S32_MAX)
481*22dc650dSSadaf Ebrahimi 				total_size = 1;
482*22dc650dSSadaf Ebrahimi 			else if (jump->u.target < S44_MAX)
483*22dc650dSSadaf Ebrahimi 				total_size = 3;
484*22dc650dSSadaf Ebrahimi 			else if (jump->u.target <= S52_MAX)
485*22dc650dSSadaf Ebrahimi 				total_size = 4;
486*22dc650dSSadaf Ebrahimi 
487*22dc650dSSadaf Ebrahimi 			size_reduce += 5 - total_size;
488*22dc650dSSadaf Ebrahimi 			jump->flags |= total_size << JUMP_SIZE_SHIFT;
489*22dc650dSSadaf Ebrahimi #endif /* !SLJIT_CONFIG_RISCV_64 */
490*22dc650dSSadaf Ebrahimi 		}
491*22dc650dSSadaf Ebrahimi 
492*22dc650dSSadaf Ebrahimi 		jump = jump->next;
493*22dc650dSSadaf Ebrahimi 		next_jump_addr = SLJIT_GET_NEXT_ADDRESS(jump);
494*22dc650dSSadaf Ebrahimi 	}
495*22dc650dSSadaf Ebrahimi 
496*22dc650dSSadaf Ebrahimi 	compiler->size -= size_reduce;
497*22dc650dSSadaf Ebrahimi }
498*22dc650dSSadaf Ebrahimi 
sljit_generate_code(struct sljit_compiler * compiler,sljit_s32 options,void * exec_allocator_data)499*22dc650dSSadaf Ebrahimi SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compiler, sljit_s32 options, void *exec_allocator_data)
500*22dc650dSSadaf Ebrahimi {
501*22dc650dSSadaf Ebrahimi 	struct sljit_memory_fragment *buf;
502*22dc650dSSadaf Ebrahimi 	sljit_ins *code;
503*22dc650dSSadaf Ebrahimi 	sljit_ins *code_ptr;
504*22dc650dSSadaf Ebrahimi 	sljit_ins *buf_ptr;
505*22dc650dSSadaf Ebrahimi 	sljit_ins *buf_end;
506*22dc650dSSadaf Ebrahimi 	sljit_uw word_count;
507*22dc650dSSadaf Ebrahimi 	SLJIT_NEXT_DEFINE_TYPES;
508*22dc650dSSadaf Ebrahimi 	sljit_sw executable_offset;
509*22dc650dSSadaf Ebrahimi 	sljit_uw addr;
510*22dc650dSSadaf Ebrahimi 
511*22dc650dSSadaf Ebrahimi 	struct sljit_label *label;
512*22dc650dSSadaf Ebrahimi 	struct sljit_jump *jump;
513*22dc650dSSadaf Ebrahimi 	struct sljit_const *const_;
514*22dc650dSSadaf Ebrahimi 
515*22dc650dSSadaf Ebrahimi 	CHECK_ERROR_PTR();
516*22dc650dSSadaf Ebrahimi 	CHECK_PTR(check_sljit_generate_code(compiler));
517*22dc650dSSadaf Ebrahimi 
518*22dc650dSSadaf Ebrahimi 	reduce_code_size(compiler);
519*22dc650dSSadaf Ebrahimi 
520*22dc650dSSadaf Ebrahimi 	code = (sljit_ins*)allocate_executable_memory(compiler->size * sizeof(sljit_ins), options, exec_allocator_data, &executable_offset);
521*22dc650dSSadaf Ebrahimi 	PTR_FAIL_WITH_EXEC_IF(code);
522*22dc650dSSadaf Ebrahimi 
523*22dc650dSSadaf Ebrahimi 	reverse_buf(compiler);
524*22dc650dSSadaf Ebrahimi 	buf = compiler->buf;
525*22dc650dSSadaf Ebrahimi 
526*22dc650dSSadaf Ebrahimi 	code_ptr = code;
527*22dc650dSSadaf Ebrahimi 	word_count = 0;
528*22dc650dSSadaf Ebrahimi 	label = compiler->labels;
529*22dc650dSSadaf Ebrahimi 	jump = compiler->jumps;
530*22dc650dSSadaf Ebrahimi 	const_ = compiler->consts;
531*22dc650dSSadaf Ebrahimi 	SLJIT_NEXT_INIT_TYPES();
532*22dc650dSSadaf Ebrahimi 	SLJIT_GET_NEXT_MIN();
533*22dc650dSSadaf Ebrahimi 
534*22dc650dSSadaf Ebrahimi 	do {
535*22dc650dSSadaf Ebrahimi 		buf_ptr = (sljit_ins*)buf->memory;
536*22dc650dSSadaf Ebrahimi 		buf_end = buf_ptr + (buf->used_size >> 2);
537*22dc650dSSadaf Ebrahimi 		do {
538*22dc650dSSadaf Ebrahimi 			*code_ptr = *buf_ptr++;
539*22dc650dSSadaf Ebrahimi 			if (next_min_addr == word_count) {
540*22dc650dSSadaf Ebrahimi 				SLJIT_ASSERT(!label || label->size >= word_count);
541*22dc650dSSadaf Ebrahimi 				SLJIT_ASSERT(!jump || jump->addr >= word_count);
542*22dc650dSSadaf Ebrahimi 				SLJIT_ASSERT(!const_ || const_->addr >= word_count);
543*22dc650dSSadaf Ebrahimi 
544*22dc650dSSadaf Ebrahimi 				/* These structures are ordered by their address. */
545*22dc650dSSadaf Ebrahimi 				if (next_min_addr == next_label_size) {
546*22dc650dSSadaf Ebrahimi 					label->u.addr = (sljit_uw)SLJIT_ADD_EXEC_OFFSET(code_ptr, executable_offset);
547*22dc650dSSadaf Ebrahimi 					label->size = (sljit_uw)(code_ptr - code);
548*22dc650dSSadaf Ebrahimi 					label = label->next;
549*22dc650dSSadaf Ebrahimi 					next_label_size = SLJIT_GET_NEXT_SIZE(label);
550*22dc650dSSadaf Ebrahimi 				}
551*22dc650dSSadaf Ebrahimi 
552*22dc650dSSadaf Ebrahimi 				if (next_min_addr == next_jump_addr) {
553*22dc650dSSadaf Ebrahimi 					if (!(jump->flags & JUMP_MOV_ADDR)) {
554*22dc650dSSadaf Ebrahimi 						word_count = word_count - 1 + (jump->flags >> JUMP_SIZE_SHIFT);
555*22dc650dSSadaf Ebrahimi 						jump->addr = (sljit_uw)code_ptr;
556*22dc650dSSadaf Ebrahimi 						code_ptr = detect_jump_type(jump, code, executable_offset);
557*22dc650dSSadaf Ebrahimi 						SLJIT_ASSERT((jump->flags & PATCH_B) || ((sljit_uw)code_ptr - jump->addr < (jump->flags >> JUMP_SIZE_SHIFT) * sizeof(sljit_ins)));
558*22dc650dSSadaf Ebrahimi 					} else {
559*22dc650dSSadaf Ebrahimi #if (defined SLJIT_CONFIG_RISCV_32 && SLJIT_CONFIG_RISCV_32)
560*22dc650dSSadaf Ebrahimi 						word_count += 1;
561*22dc650dSSadaf Ebrahimi 						jump->addr = (sljit_uw)code_ptr;
562*22dc650dSSadaf Ebrahimi 						code_ptr += 1;
563*22dc650dSSadaf Ebrahimi #else /* !SLJIT_CONFIG_RISCV_32 */
564*22dc650dSSadaf Ebrahimi 						word_count += jump->flags >> JUMP_SIZE_SHIFT;
565*22dc650dSSadaf Ebrahimi 						addr = (sljit_uw)code_ptr;
566*22dc650dSSadaf Ebrahimi 						code_ptr += mov_addr_get_length(jump, code_ptr, code, executable_offset);
567*22dc650dSSadaf Ebrahimi 						jump->addr = addr;
568*22dc650dSSadaf Ebrahimi #endif /* SLJIT_CONFIG_RISCV_32 */
569*22dc650dSSadaf Ebrahimi 					}
570*22dc650dSSadaf Ebrahimi 					jump = jump->next;
571*22dc650dSSadaf Ebrahimi 					next_jump_addr = SLJIT_GET_NEXT_ADDRESS(jump);
572*22dc650dSSadaf Ebrahimi 				} else if (next_min_addr == next_const_addr) {
573*22dc650dSSadaf Ebrahimi 					const_->addr = (sljit_uw)code_ptr;
574*22dc650dSSadaf Ebrahimi 					const_ = const_->next;
575*22dc650dSSadaf Ebrahimi 					next_const_addr = SLJIT_GET_NEXT_ADDRESS(const_);
576*22dc650dSSadaf Ebrahimi 				}
577*22dc650dSSadaf Ebrahimi 
578*22dc650dSSadaf Ebrahimi 				SLJIT_GET_NEXT_MIN();
579*22dc650dSSadaf Ebrahimi 			}
580*22dc650dSSadaf Ebrahimi 			code_ptr++;
581*22dc650dSSadaf Ebrahimi 			word_count++;
582*22dc650dSSadaf Ebrahimi 		} while (buf_ptr < buf_end);
583*22dc650dSSadaf Ebrahimi 
584*22dc650dSSadaf Ebrahimi 		buf = buf->next;
585*22dc650dSSadaf Ebrahimi 	} while (buf);
586*22dc650dSSadaf Ebrahimi 
587*22dc650dSSadaf Ebrahimi 	if (label && label->size == word_count) {
588*22dc650dSSadaf Ebrahimi 		label->u.addr = (sljit_uw)code_ptr;
589*22dc650dSSadaf Ebrahimi 		label->size = (sljit_uw)(code_ptr - code);
590*22dc650dSSadaf Ebrahimi 		label = label->next;
591*22dc650dSSadaf Ebrahimi 	}
592*22dc650dSSadaf Ebrahimi 
593*22dc650dSSadaf Ebrahimi 	SLJIT_ASSERT(!label);
594*22dc650dSSadaf Ebrahimi 	SLJIT_ASSERT(!jump);
595*22dc650dSSadaf Ebrahimi 	SLJIT_ASSERT(!const_);
596*22dc650dSSadaf Ebrahimi 	SLJIT_ASSERT(code_ptr - code <= (sljit_sw)compiler->size);
597*22dc650dSSadaf Ebrahimi 
598*22dc650dSSadaf Ebrahimi 	jump = compiler->jumps;
599*22dc650dSSadaf Ebrahimi 	while (jump) {
600*22dc650dSSadaf Ebrahimi 		do {
601*22dc650dSSadaf Ebrahimi 			if (!(jump->flags & (PATCH_B | PATCH_J)) || (jump->flags & JUMP_MOV_ADDR)) {
602*22dc650dSSadaf Ebrahimi 				load_addr_to_reg(jump, executable_offset);
603*22dc650dSSadaf Ebrahimi 				break;
604*22dc650dSSadaf Ebrahimi 			}
605*22dc650dSSadaf Ebrahimi 
606*22dc650dSSadaf Ebrahimi 			addr = (jump->flags & JUMP_ADDR) ? jump->u.target : jump->u.label->u.addr;
607*22dc650dSSadaf Ebrahimi 			buf_ptr = (sljit_ins *)jump->addr;
608*22dc650dSSadaf Ebrahimi 			addr -= (sljit_uw)SLJIT_ADD_EXEC_OFFSET(buf_ptr, executable_offset);
609*22dc650dSSadaf Ebrahimi 
610*22dc650dSSadaf Ebrahimi 			if (jump->flags & PATCH_B) {
611*22dc650dSSadaf Ebrahimi 				SLJIT_ASSERT((sljit_sw)addr >= BRANCH_MIN && (sljit_sw)addr <= BRANCH_MAX);
612*22dc650dSSadaf Ebrahimi 				addr = ((addr & 0x800) >> 4) | ((addr & 0x1e) << 7) | ((addr & 0x7e0) << 20) | ((addr & 0x1000) << 19);
613*22dc650dSSadaf Ebrahimi 				buf_ptr[0] |= (sljit_ins)addr;
614*22dc650dSSadaf Ebrahimi 				break;
615*22dc650dSSadaf Ebrahimi 			}
616*22dc650dSSadaf Ebrahimi 
617*22dc650dSSadaf Ebrahimi 			SLJIT_ASSERT((sljit_sw)addr >= JUMP_MIN && (sljit_sw)addr <= JUMP_MAX);
618*22dc650dSSadaf Ebrahimi 			addr = (addr & 0xff000) | ((addr & 0x800) << 9) | ((addr & 0x7fe) << 20) | ((addr & 0x100000) << 11);
619*22dc650dSSadaf Ebrahimi 			buf_ptr[0] = JAL | RD((jump->flags & IS_CALL) ? RETURN_ADDR_REG : TMP_ZERO) | (sljit_ins)addr;
620*22dc650dSSadaf Ebrahimi 		} while (0);
621*22dc650dSSadaf Ebrahimi 
622*22dc650dSSadaf Ebrahimi 		jump = jump->next;
623*22dc650dSSadaf Ebrahimi 	}
624*22dc650dSSadaf Ebrahimi 
625*22dc650dSSadaf Ebrahimi 	compiler->error = SLJIT_ERR_COMPILED;
626*22dc650dSSadaf Ebrahimi 	compiler->executable_offset = executable_offset;
627*22dc650dSSadaf Ebrahimi 	compiler->executable_size = (sljit_uw)(code_ptr - code) * sizeof(sljit_ins);
628*22dc650dSSadaf Ebrahimi 
629*22dc650dSSadaf Ebrahimi 	code = (sljit_ins *)SLJIT_ADD_EXEC_OFFSET(code, executable_offset);
630*22dc650dSSadaf Ebrahimi 	code_ptr = (sljit_ins *)SLJIT_ADD_EXEC_OFFSET(code_ptr, executable_offset);
631*22dc650dSSadaf Ebrahimi 
632*22dc650dSSadaf Ebrahimi 	SLJIT_CACHE_FLUSH(code, code_ptr);
633*22dc650dSSadaf Ebrahimi 	SLJIT_UPDATE_WX_FLAGS(code, code_ptr, 1);
634*22dc650dSSadaf Ebrahimi 	return code;
635*22dc650dSSadaf Ebrahimi }
636*22dc650dSSadaf Ebrahimi 
sljit_has_cpu_feature(sljit_s32 feature_type)637*22dc650dSSadaf Ebrahimi SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_has_cpu_feature(sljit_s32 feature_type)
638*22dc650dSSadaf Ebrahimi {
639*22dc650dSSadaf Ebrahimi 	switch (feature_type) {
640*22dc650dSSadaf Ebrahimi 	case SLJIT_HAS_FPU:
641*22dc650dSSadaf Ebrahimi #ifdef SLJIT_IS_FPU_AVAILABLE
642*22dc650dSSadaf Ebrahimi 		return (SLJIT_IS_FPU_AVAILABLE) != 0;
643*22dc650dSSadaf Ebrahimi #elif defined(__riscv_float_abi_soft)
644*22dc650dSSadaf Ebrahimi 		return 0;
645*22dc650dSSadaf Ebrahimi #else
646*22dc650dSSadaf Ebrahimi 		return 1;
647*22dc650dSSadaf Ebrahimi #endif /* SLJIT_IS_FPU_AVAILABLE */
648*22dc650dSSadaf Ebrahimi 	case SLJIT_HAS_ZERO_REGISTER:
649*22dc650dSSadaf Ebrahimi 	case SLJIT_HAS_COPY_F32:
650*22dc650dSSadaf Ebrahimi #if (defined SLJIT_CONFIG_RISCV_64 && SLJIT_CONFIG_RISCV_64)
651*22dc650dSSadaf Ebrahimi 	case SLJIT_HAS_COPY_F64:
652*22dc650dSSadaf Ebrahimi #endif /* !SLJIT_CONFIG_RISCV_64 */
653*22dc650dSSadaf Ebrahimi 		return 1;
654*22dc650dSSadaf Ebrahimi 	default:
655*22dc650dSSadaf Ebrahimi 		return 0;
656*22dc650dSSadaf Ebrahimi 	}
657*22dc650dSSadaf Ebrahimi }
658*22dc650dSSadaf Ebrahimi 
sljit_cmp_info(sljit_s32 type)659*22dc650dSSadaf Ebrahimi SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_cmp_info(sljit_s32 type)
660*22dc650dSSadaf Ebrahimi {
661*22dc650dSSadaf Ebrahimi 	switch (type) {
662*22dc650dSSadaf Ebrahimi 	case SLJIT_UNORDERED_OR_EQUAL:
663*22dc650dSSadaf Ebrahimi 	case SLJIT_ORDERED_NOT_EQUAL:
664*22dc650dSSadaf Ebrahimi 		return 2;
665*22dc650dSSadaf Ebrahimi 
666*22dc650dSSadaf Ebrahimi 	case SLJIT_UNORDERED:
667*22dc650dSSadaf Ebrahimi 	case SLJIT_ORDERED:
668*22dc650dSSadaf Ebrahimi 		return 1;
669*22dc650dSSadaf Ebrahimi 	}
670*22dc650dSSadaf Ebrahimi 
671*22dc650dSSadaf Ebrahimi 	return 0;
672*22dc650dSSadaf Ebrahimi }
673*22dc650dSSadaf Ebrahimi 
674*22dc650dSSadaf Ebrahimi /* --------------------------------------------------------------------- */
675*22dc650dSSadaf Ebrahimi /*  Entry, exit                                                          */
676*22dc650dSSadaf Ebrahimi /* --------------------------------------------------------------------- */
677*22dc650dSSadaf Ebrahimi 
678*22dc650dSSadaf Ebrahimi /* Creates an index in data_transfer_insts array. */
679*22dc650dSSadaf Ebrahimi #define LOAD_DATA	0x01
680*22dc650dSSadaf Ebrahimi #define WORD_DATA	0x00
681*22dc650dSSadaf Ebrahimi #define BYTE_DATA	0x02
682*22dc650dSSadaf Ebrahimi #define HALF_DATA	0x04
683*22dc650dSSadaf Ebrahimi #define INT_DATA	0x06
684*22dc650dSSadaf Ebrahimi #define SIGNED_DATA	0x08
685*22dc650dSSadaf Ebrahimi /* Separates integer and floating point registers */
686*22dc650dSSadaf Ebrahimi #define GPR_REG		0x0f
687*22dc650dSSadaf Ebrahimi #define DOUBLE_DATA	0x10
688*22dc650dSSadaf Ebrahimi #define SINGLE_DATA	0x12
689*22dc650dSSadaf Ebrahimi 
690*22dc650dSSadaf Ebrahimi #define MEM_MASK	0x1f
691*22dc650dSSadaf Ebrahimi 
692*22dc650dSSadaf Ebrahimi #define ARG_TEST	0x00020
693*22dc650dSSadaf Ebrahimi #define ALT_KEEP_CACHE	0x00040
694*22dc650dSSadaf Ebrahimi #define CUMULATIVE_OP	0x00080
695*22dc650dSSadaf Ebrahimi #define IMM_OP		0x00100
696*22dc650dSSadaf Ebrahimi #define MOVE_OP		0x00200
697*22dc650dSSadaf Ebrahimi #define SRC2_IMM	0x00400
698*22dc650dSSadaf Ebrahimi 
699*22dc650dSSadaf Ebrahimi #define UNUSED_DEST	0x00800
700*22dc650dSSadaf Ebrahimi #define REG_DEST	0x01000
701*22dc650dSSadaf Ebrahimi #define REG1_SOURCE	0x02000
702*22dc650dSSadaf Ebrahimi #define REG2_SOURCE	0x04000
703*22dc650dSSadaf Ebrahimi #define SLOW_SRC1	0x08000
704*22dc650dSSadaf Ebrahimi #define SLOW_SRC2	0x10000
705*22dc650dSSadaf Ebrahimi #define SLOW_DEST	0x20000
706*22dc650dSSadaf Ebrahimi #define MEM_USE_TMP2	0x40000
707*22dc650dSSadaf Ebrahimi 
708*22dc650dSSadaf Ebrahimi #if (defined SLJIT_CONFIG_RISCV_32 && SLJIT_CONFIG_RISCV_32)
709*22dc650dSSadaf Ebrahimi #define STACK_STORE	SW
710*22dc650dSSadaf Ebrahimi #define STACK_LOAD	LW
711*22dc650dSSadaf Ebrahimi #else
712*22dc650dSSadaf Ebrahimi #define STACK_STORE	SD
713*22dc650dSSadaf Ebrahimi #define STACK_LOAD	LD
714*22dc650dSSadaf Ebrahimi #endif
715*22dc650dSSadaf Ebrahimi 
716*22dc650dSSadaf Ebrahimi #if (defined SLJIT_CONFIG_RISCV_32 && SLJIT_CONFIG_RISCV_32)
717*22dc650dSSadaf Ebrahimi #include "sljitNativeRISCV_32.c"
718*22dc650dSSadaf Ebrahimi #else
719*22dc650dSSadaf Ebrahimi #include "sljitNativeRISCV_64.c"
720*22dc650dSSadaf Ebrahimi #endif
721*22dc650dSSadaf Ebrahimi 
722*22dc650dSSadaf Ebrahimi #define STACK_MAX_DISTANCE (-SIMM_MIN)
723*22dc650dSSadaf Ebrahimi 
724*22dc650dSSadaf Ebrahimi static sljit_s32 emit_op_mem(struct sljit_compiler *compiler, sljit_s32 flags, sljit_s32 reg, sljit_s32 arg, sljit_sw argw);
725*22dc650dSSadaf Ebrahimi 
sljit_emit_enter(struct sljit_compiler * compiler,sljit_s32 options,sljit_s32 arg_types,sljit_s32 scratches,sljit_s32 saveds,sljit_s32 fscratches,sljit_s32 fsaveds,sljit_s32 local_size)726*22dc650dSSadaf Ebrahimi SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_enter(struct sljit_compiler *compiler,
727*22dc650dSSadaf Ebrahimi 	sljit_s32 options, sljit_s32 arg_types, sljit_s32 scratches, sljit_s32 saveds,
728*22dc650dSSadaf Ebrahimi 	sljit_s32 fscratches, sljit_s32 fsaveds, sljit_s32 local_size)
729*22dc650dSSadaf Ebrahimi {
730*22dc650dSSadaf Ebrahimi 	sljit_s32 i, tmp, offset;
731*22dc650dSSadaf Ebrahimi 	sljit_s32 saved_arg_count = SLJIT_KEPT_SAVEDS_COUNT(options);
732*22dc650dSSadaf Ebrahimi 
733*22dc650dSSadaf Ebrahimi 	CHECK_ERROR();
734*22dc650dSSadaf Ebrahimi 	CHECK(check_sljit_emit_enter(compiler, options, arg_types, scratches, saveds, fscratches, fsaveds, local_size));
735*22dc650dSSadaf Ebrahimi 	set_emit_enter(compiler, options, arg_types, scratches, saveds, fscratches, fsaveds, local_size);
736*22dc650dSSadaf Ebrahimi 
737*22dc650dSSadaf Ebrahimi 	local_size += GET_SAVED_REGISTERS_SIZE(scratches, saveds - saved_arg_count, 1);
738*22dc650dSSadaf Ebrahimi #if (defined SLJIT_CONFIG_RISCV_32 && SLJIT_CONFIG_RISCV_32)
739*22dc650dSSadaf Ebrahimi 	if (fsaveds > 0 || fscratches >= SLJIT_FIRST_SAVED_FLOAT_REG) {
740*22dc650dSSadaf Ebrahimi 		if ((local_size & SSIZE_OF(sw)) != 0)
741*22dc650dSSadaf Ebrahimi 			local_size += SSIZE_OF(sw);
742*22dc650dSSadaf Ebrahimi 		local_size += GET_SAVED_FLOAT_REGISTERS_SIZE(fscratches, fsaveds, f64);
743*22dc650dSSadaf Ebrahimi 	}
744*22dc650dSSadaf Ebrahimi #else
745*22dc650dSSadaf Ebrahimi 	local_size += GET_SAVED_FLOAT_REGISTERS_SIZE(fscratches, fsaveds, f64);
746*22dc650dSSadaf Ebrahimi #endif
747*22dc650dSSadaf Ebrahimi 	local_size = (local_size + SLJIT_LOCALS_OFFSET + 15) & ~0xf;
748*22dc650dSSadaf Ebrahimi 	compiler->local_size = local_size;
749*22dc650dSSadaf Ebrahimi 
750*22dc650dSSadaf Ebrahimi 	if (local_size <= STACK_MAX_DISTANCE) {
751*22dc650dSSadaf Ebrahimi 		/* Frequent case. */
752*22dc650dSSadaf Ebrahimi 		FAIL_IF(push_inst(compiler, ADDI | RD(SLJIT_SP) | RS1(SLJIT_SP) | IMM_I(-local_size)));
753*22dc650dSSadaf Ebrahimi 		offset = local_size - SSIZE_OF(sw);
754*22dc650dSSadaf Ebrahimi 		local_size = 0;
755*22dc650dSSadaf Ebrahimi 	} else {
756*22dc650dSSadaf Ebrahimi 		FAIL_IF(push_inst(compiler, ADDI | RD(SLJIT_SP) | RS1(SLJIT_SP) | IMM_I(STACK_MAX_DISTANCE)));
757*22dc650dSSadaf Ebrahimi 		local_size -= STACK_MAX_DISTANCE;
758*22dc650dSSadaf Ebrahimi 
759*22dc650dSSadaf Ebrahimi 		if (local_size > STACK_MAX_DISTANCE)
760*22dc650dSSadaf Ebrahimi 			FAIL_IF(load_immediate(compiler, TMP_REG1, local_size, TMP_REG3));
761*22dc650dSSadaf Ebrahimi 		offset = STACK_MAX_DISTANCE - SSIZE_OF(sw);
762*22dc650dSSadaf Ebrahimi 	}
763*22dc650dSSadaf Ebrahimi 
764*22dc650dSSadaf Ebrahimi 	FAIL_IF(push_imm_s_inst(compiler, STACK_STORE | RS1(SLJIT_SP) | RS2(RETURN_ADDR_REG), offset));
765*22dc650dSSadaf Ebrahimi 
766*22dc650dSSadaf Ebrahimi 	tmp = SLJIT_S0 - saveds;
767*22dc650dSSadaf Ebrahimi 	for (i = SLJIT_S0 - saved_arg_count; i > tmp; i--) {
768*22dc650dSSadaf Ebrahimi 		offset -= SSIZE_OF(sw);
769*22dc650dSSadaf Ebrahimi 		FAIL_IF(push_imm_s_inst(compiler, STACK_STORE | RS1(SLJIT_SP) | RS2(i), offset));
770*22dc650dSSadaf Ebrahimi 	}
771*22dc650dSSadaf Ebrahimi 
772*22dc650dSSadaf Ebrahimi 	for (i = scratches; i >= SLJIT_FIRST_SAVED_REG; i--) {
773*22dc650dSSadaf Ebrahimi 		offset -= SSIZE_OF(sw);
774*22dc650dSSadaf Ebrahimi 		FAIL_IF(push_imm_s_inst(compiler, STACK_STORE | RS1(SLJIT_SP) | RS2(i), offset));
775*22dc650dSSadaf Ebrahimi 	}
776*22dc650dSSadaf Ebrahimi 
777*22dc650dSSadaf Ebrahimi #if (defined SLJIT_CONFIG_RISCV_32 && SLJIT_CONFIG_RISCV_32)
778*22dc650dSSadaf Ebrahimi 	/* This alignment is valid because offset is not used after storing FPU regs. */
779*22dc650dSSadaf Ebrahimi 	if ((offset & SSIZE_OF(sw)) != 0)
780*22dc650dSSadaf Ebrahimi 		offset -= SSIZE_OF(sw);
781*22dc650dSSadaf Ebrahimi #endif
782*22dc650dSSadaf Ebrahimi 
783*22dc650dSSadaf Ebrahimi 	tmp = SLJIT_FS0 - fsaveds;
784*22dc650dSSadaf Ebrahimi 	for (i = SLJIT_FS0; i > tmp; i--) {
785*22dc650dSSadaf Ebrahimi 		offset -= SSIZE_OF(f64);
786*22dc650dSSadaf Ebrahimi 		FAIL_IF(push_imm_s_inst(compiler, FSD | RS1(SLJIT_SP) | FRS2(i), offset));
787*22dc650dSSadaf Ebrahimi 	}
788*22dc650dSSadaf Ebrahimi 
789*22dc650dSSadaf Ebrahimi 	for (i = fscratches; i >= SLJIT_FIRST_SAVED_FLOAT_REG; i--) {
790*22dc650dSSadaf Ebrahimi 		offset -= SSIZE_OF(f64);
791*22dc650dSSadaf Ebrahimi 		FAIL_IF(push_imm_s_inst(compiler, FSD | RS1(SLJIT_SP) | FRS2(i), offset));
792*22dc650dSSadaf Ebrahimi 	}
793*22dc650dSSadaf Ebrahimi 
794*22dc650dSSadaf Ebrahimi 	if (local_size > STACK_MAX_DISTANCE)
795*22dc650dSSadaf Ebrahimi 		FAIL_IF(push_inst(compiler, SUB | RD(SLJIT_SP) | RS1(SLJIT_SP) | RS2(TMP_REG1)));
796*22dc650dSSadaf Ebrahimi 	else if (local_size > 0)
797*22dc650dSSadaf Ebrahimi 		FAIL_IF(push_inst(compiler, ADDI | RD(SLJIT_SP) | RS1(SLJIT_SP) | IMM_I(-local_size)));
798*22dc650dSSadaf Ebrahimi 
799*22dc650dSSadaf Ebrahimi 	if (options & SLJIT_ENTER_REG_ARG)
800*22dc650dSSadaf Ebrahimi 		return SLJIT_SUCCESS;
801*22dc650dSSadaf Ebrahimi 
802*22dc650dSSadaf Ebrahimi 	arg_types >>= SLJIT_ARG_SHIFT;
803*22dc650dSSadaf Ebrahimi 	saved_arg_count = 0;
804*22dc650dSSadaf Ebrahimi 	tmp = SLJIT_R0;
805*22dc650dSSadaf Ebrahimi 
806*22dc650dSSadaf Ebrahimi 	while (arg_types > 0) {
807*22dc650dSSadaf Ebrahimi 		if ((arg_types & SLJIT_ARG_MASK) < SLJIT_ARG_TYPE_F64) {
808*22dc650dSSadaf Ebrahimi 			if (!(arg_types & SLJIT_ARG_TYPE_SCRATCH_REG)) {
809*22dc650dSSadaf Ebrahimi 				FAIL_IF(push_inst(compiler, ADDI | RD(SLJIT_S0 - saved_arg_count) | RS1(tmp) | IMM_I(0)));
810*22dc650dSSadaf Ebrahimi 				saved_arg_count++;
811*22dc650dSSadaf Ebrahimi 			}
812*22dc650dSSadaf Ebrahimi 			tmp++;
813*22dc650dSSadaf Ebrahimi 		}
814*22dc650dSSadaf Ebrahimi 
815*22dc650dSSadaf Ebrahimi 		arg_types >>= SLJIT_ARG_SHIFT;
816*22dc650dSSadaf Ebrahimi 	}
817*22dc650dSSadaf Ebrahimi 
818*22dc650dSSadaf Ebrahimi 	return SLJIT_SUCCESS;
819*22dc650dSSadaf Ebrahimi }
820*22dc650dSSadaf Ebrahimi 
821*22dc650dSSadaf Ebrahimi #undef STACK_MAX_DISTANCE
822*22dc650dSSadaf Ebrahimi 
sljit_set_context(struct sljit_compiler * compiler,sljit_s32 options,sljit_s32 arg_types,sljit_s32 scratches,sljit_s32 saveds,sljit_s32 fscratches,sljit_s32 fsaveds,sljit_s32 local_size)823*22dc650dSSadaf Ebrahimi SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_set_context(struct sljit_compiler *compiler,
824*22dc650dSSadaf Ebrahimi 	sljit_s32 options, sljit_s32 arg_types, sljit_s32 scratches, sljit_s32 saveds,
825*22dc650dSSadaf Ebrahimi 	sljit_s32 fscratches, sljit_s32 fsaveds, sljit_s32 local_size)
826*22dc650dSSadaf Ebrahimi {
827*22dc650dSSadaf Ebrahimi 	CHECK_ERROR();
828*22dc650dSSadaf Ebrahimi 	CHECK(check_sljit_set_context(compiler, options, arg_types, scratches, saveds, fscratches, fsaveds, local_size));
829*22dc650dSSadaf Ebrahimi 	set_set_context(compiler, options, arg_types, scratches, saveds, fscratches, fsaveds, local_size);
830*22dc650dSSadaf Ebrahimi 
831*22dc650dSSadaf Ebrahimi 	local_size += GET_SAVED_REGISTERS_SIZE(scratches, saveds - SLJIT_KEPT_SAVEDS_COUNT(options), 1);
832*22dc650dSSadaf Ebrahimi #if (defined SLJIT_CONFIG_RISCV_32 && SLJIT_CONFIG_RISCV_32)
833*22dc650dSSadaf Ebrahimi 	if (fsaveds > 0 || fscratches >= SLJIT_FIRST_SAVED_FLOAT_REG) {
834*22dc650dSSadaf Ebrahimi 		if ((local_size & SSIZE_OF(sw)) != 0)
835*22dc650dSSadaf Ebrahimi 			local_size += SSIZE_OF(sw);
836*22dc650dSSadaf Ebrahimi 		local_size += GET_SAVED_FLOAT_REGISTERS_SIZE(fscratches, fsaveds, f64);
837*22dc650dSSadaf Ebrahimi 	}
838*22dc650dSSadaf Ebrahimi #else
839*22dc650dSSadaf Ebrahimi 	local_size += GET_SAVED_FLOAT_REGISTERS_SIZE(fscratches, fsaveds, f64);
840*22dc650dSSadaf Ebrahimi #endif
841*22dc650dSSadaf Ebrahimi 	compiler->local_size = (local_size + SLJIT_LOCALS_OFFSET + 15) & ~0xf;
842*22dc650dSSadaf Ebrahimi 
843*22dc650dSSadaf Ebrahimi 	return SLJIT_SUCCESS;
844*22dc650dSSadaf Ebrahimi }
845*22dc650dSSadaf Ebrahimi 
846*22dc650dSSadaf Ebrahimi #define STACK_MAX_DISTANCE (-SIMM_MIN - 16)
847*22dc650dSSadaf Ebrahimi 
emit_stack_frame_release(struct sljit_compiler * compiler,sljit_s32 is_return_to)848*22dc650dSSadaf Ebrahimi static sljit_s32 emit_stack_frame_release(struct sljit_compiler *compiler, sljit_s32 is_return_to)
849*22dc650dSSadaf Ebrahimi {
850*22dc650dSSadaf Ebrahimi 	sljit_s32 i, tmp, offset;
851*22dc650dSSadaf Ebrahimi 	sljit_s32 local_size = compiler->local_size;
852*22dc650dSSadaf Ebrahimi 
853*22dc650dSSadaf Ebrahimi 	if (local_size > STACK_MAX_DISTANCE) {
854*22dc650dSSadaf Ebrahimi 		local_size -= STACK_MAX_DISTANCE;
855*22dc650dSSadaf Ebrahimi 
856*22dc650dSSadaf Ebrahimi 		if (local_size > STACK_MAX_DISTANCE) {
857*22dc650dSSadaf Ebrahimi 			FAIL_IF(load_immediate(compiler, TMP_REG2, local_size, TMP_REG3));
858*22dc650dSSadaf Ebrahimi 			FAIL_IF(push_inst(compiler, ADD | RD(SLJIT_SP) | RS1(SLJIT_SP) | RS2(TMP_REG2)));
859*22dc650dSSadaf Ebrahimi 		} else
860*22dc650dSSadaf Ebrahimi 			FAIL_IF(push_inst(compiler, ADDI | RD(SLJIT_SP) | RS1(SLJIT_SP) | IMM_I(local_size)));
861*22dc650dSSadaf Ebrahimi 
862*22dc650dSSadaf Ebrahimi 		local_size = STACK_MAX_DISTANCE;
863*22dc650dSSadaf Ebrahimi 	}
864*22dc650dSSadaf Ebrahimi 
865*22dc650dSSadaf Ebrahimi 	SLJIT_ASSERT(local_size > 0);
866*22dc650dSSadaf Ebrahimi 
867*22dc650dSSadaf Ebrahimi 	offset = local_size - SSIZE_OF(sw);
868*22dc650dSSadaf Ebrahimi 	if (!is_return_to)
869*22dc650dSSadaf Ebrahimi 		FAIL_IF(push_inst(compiler, STACK_LOAD | RD(RETURN_ADDR_REG) | RS1(SLJIT_SP) | IMM_I(offset)));
870*22dc650dSSadaf Ebrahimi 
871*22dc650dSSadaf Ebrahimi 	tmp = SLJIT_S0 - compiler->saveds;
872*22dc650dSSadaf Ebrahimi 	for (i = SLJIT_S0 - SLJIT_KEPT_SAVEDS_COUNT(compiler->options); i > tmp; i--) {
873*22dc650dSSadaf Ebrahimi 		offset -= SSIZE_OF(sw);
874*22dc650dSSadaf Ebrahimi 		FAIL_IF(push_inst(compiler, STACK_LOAD | RD(i) | RS1(SLJIT_SP) | IMM_I(offset)));
875*22dc650dSSadaf Ebrahimi 	}
876*22dc650dSSadaf Ebrahimi 
877*22dc650dSSadaf Ebrahimi 	for (i = compiler->scratches; i >= SLJIT_FIRST_SAVED_REG; i--) {
878*22dc650dSSadaf Ebrahimi 		offset -= SSIZE_OF(sw);
879*22dc650dSSadaf Ebrahimi 		FAIL_IF(push_inst(compiler, STACK_LOAD | RD(i) | RS1(SLJIT_SP) | IMM_I(offset)));
880*22dc650dSSadaf Ebrahimi 	}
881*22dc650dSSadaf Ebrahimi 
882*22dc650dSSadaf Ebrahimi #if (defined SLJIT_CONFIG_RISCV_32 && SLJIT_CONFIG_RISCV_32)
883*22dc650dSSadaf Ebrahimi 	/* This alignment is valid because offset is not used after storing FPU regs. */
884*22dc650dSSadaf Ebrahimi 	if ((offset & SSIZE_OF(sw)) != 0)
885*22dc650dSSadaf Ebrahimi 		offset -= SSIZE_OF(sw);
886*22dc650dSSadaf Ebrahimi #endif
887*22dc650dSSadaf Ebrahimi 
888*22dc650dSSadaf Ebrahimi 	tmp = SLJIT_FS0 - compiler->fsaveds;
889*22dc650dSSadaf Ebrahimi 	for (i = SLJIT_FS0; i > tmp; i--) {
890*22dc650dSSadaf Ebrahimi 		offset -= SSIZE_OF(f64);
891*22dc650dSSadaf Ebrahimi 		FAIL_IF(push_inst(compiler, FLD | FRD(i) | RS1(SLJIT_SP) | IMM_I(offset)));
892*22dc650dSSadaf Ebrahimi 	}
893*22dc650dSSadaf Ebrahimi 
894*22dc650dSSadaf Ebrahimi 	for (i = compiler->fscratches; i >= SLJIT_FIRST_SAVED_FLOAT_REG; i--) {
895*22dc650dSSadaf Ebrahimi 		offset -= SSIZE_OF(f64);
896*22dc650dSSadaf Ebrahimi 		FAIL_IF(push_inst(compiler, FLD | FRD(i) | RS1(SLJIT_SP) | IMM_I(offset)));
897*22dc650dSSadaf Ebrahimi 	}
898*22dc650dSSadaf Ebrahimi 
899*22dc650dSSadaf Ebrahimi 	return push_inst(compiler, ADDI | RD(SLJIT_SP) | RS1(SLJIT_SP) | IMM_I(local_size));
900*22dc650dSSadaf Ebrahimi }
901*22dc650dSSadaf Ebrahimi 
902*22dc650dSSadaf Ebrahimi #undef STACK_MAX_DISTANCE
903*22dc650dSSadaf Ebrahimi 
sljit_emit_return_void(struct sljit_compiler * compiler)904*22dc650dSSadaf Ebrahimi SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_return_void(struct sljit_compiler *compiler)
905*22dc650dSSadaf Ebrahimi {
906*22dc650dSSadaf Ebrahimi 	CHECK_ERROR();
907*22dc650dSSadaf Ebrahimi 	CHECK(check_sljit_emit_return_void(compiler));
908*22dc650dSSadaf Ebrahimi 
909*22dc650dSSadaf Ebrahimi 	FAIL_IF(emit_stack_frame_release(compiler, 0));
910*22dc650dSSadaf Ebrahimi 	return push_inst(compiler, JALR | RD(TMP_ZERO) | RS1(RETURN_ADDR_REG) | IMM_I(0));
911*22dc650dSSadaf Ebrahimi }
912*22dc650dSSadaf Ebrahimi 
sljit_emit_return_to(struct sljit_compiler * compiler,sljit_s32 src,sljit_sw srcw)913*22dc650dSSadaf Ebrahimi SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_return_to(struct sljit_compiler *compiler,
914*22dc650dSSadaf Ebrahimi 	sljit_s32 src, sljit_sw srcw)
915*22dc650dSSadaf Ebrahimi {
916*22dc650dSSadaf Ebrahimi 	CHECK_ERROR();
917*22dc650dSSadaf Ebrahimi 	CHECK(check_sljit_emit_return_to(compiler, src, srcw));
918*22dc650dSSadaf Ebrahimi 
919*22dc650dSSadaf Ebrahimi 	if (src & SLJIT_MEM) {
920*22dc650dSSadaf Ebrahimi 		ADJUST_LOCAL_OFFSET(src, srcw);
921*22dc650dSSadaf Ebrahimi 		FAIL_IF(emit_op_mem(compiler, WORD_DATA | LOAD_DATA, TMP_REG1, src, srcw));
922*22dc650dSSadaf Ebrahimi 		src = TMP_REG1;
923*22dc650dSSadaf Ebrahimi 		srcw = 0;
924*22dc650dSSadaf Ebrahimi 	} else if (src >= SLJIT_FIRST_SAVED_REG && src <= (SLJIT_S0 - SLJIT_KEPT_SAVEDS_COUNT(compiler->options))) {
925*22dc650dSSadaf Ebrahimi 		FAIL_IF(push_inst(compiler, ADDI | RD(TMP_REG1) | RS1(src) | IMM_I(0)));
926*22dc650dSSadaf Ebrahimi 		src = TMP_REG1;
927*22dc650dSSadaf Ebrahimi 		srcw = 0;
928*22dc650dSSadaf Ebrahimi 	}
929*22dc650dSSadaf Ebrahimi 
930*22dc650dSSadaf Ebrahimi 	FAIL_IF(emit_stack_frame_release(compiler, 1));
931*22dc650dSSadaf Ebrahimi 
932*22dc650dSSadaf Ebrahimi 	SLJIT_SKIP_CHECKS(compiler);
933*22dc650dSSadaf Ebrahimi 	return sljit_emit_ijump(compiler, SLJIT_JUMP, src, srcw);
934*22dc650dSSadaf Ebrahimi }
935*22dc650dSSadaf Ebrahimi 
936*22dc650dSSadaf Ebrahimi /* --------------------------------------------------------------------- */
937*22dc650dSSadaf Ebrahimi /*  Operators                                                            */
938*22dc650dSSadaf Ebrahimi /* --------------------------------------------------------------------- */
939*22dc650dSSadaf Ebrahimi 
940*22dc650dSSadaf Ebrahimi #if (defined SLJIT_CONFIG_RISCV_32 && SLJIT_CONFIG_RISCV_32)
941*22dc650dSSadaf Ebrahimi #define ARCH_32_64(a, b)	a
942*22dc650dSSadaf Ebrahimi #else
943*22dc650dSSadaf Ebrahimi #define ARCH_32_64(a, b)	b
944*22dc650dSSadaf Ebrahimi #endif
945*22dc650dSSadaf Ebrahimi 
946*22dc650dSSadaf Ebrahimi static const sljit_ins data_transfer_insts[16 + 4] = {
947*22dc650dSSadaf Ebrahimi /* u w s */ ARCH_32_64(F3(0x2) | OPC(0x23) /* sw */, F3(0x3) | OPC(0x23) /* sd */),
948*22dc650dSSadaf Ebrahimi /* u w l */ ARCH_32_64(F3(0x2) | OPC(0x3) /* lw */, F3(0x3) | OPC(0x3) /* ld */),
949*22dc650dSSadaf Ebrahimi /* u b s */ F3(0x0) | OPC(0x23) /* sb */,
950*22dc650dSSadaf Ebrahimi /* u b l */ F3(0x4) | OPC(0x3) /* lbu */,
951*22dc650dSSadaf Ebrahimi /* u h s */ F3(0x1) | OPC(0x23) /* sh */,
952*22dc650dSSadaf Ebrahimi /* u h l */ F3(0x5) | OPC(0x3) /* lhu */,
953*22dc650dSSadaf Ebrahimi /* u i s */ F3(0x2) | OPC(0x23) /* sw */,
954*22dc650dSSadaf Ebrahimi /* u i l */ ARCH_32_64(F3(0x2) | OPC(0x3) /* lw */, F3(0x6) | OPC(0x3) /* lwu */),
955*22dc650dSSadaf Ebrahimi 
956*22dc650dSSadaf Ebrahimi /* s w s */ ARCH_32_64(F3(0x2) | OPC(0x23) /* sw */, F3(0x3) | OPC(0x23) /* sd */),
957*22dc650dSSadaf Ebrahimi /* s w l */ ARCH_32_64(F3(0x2) | OPC(0x3) /* lw */, F3(0x3) | OPC(0x3) /* ld */),
958*22dc650dSSadaf Ebrahimi /* s b s */ F3(0x0) | OPC(0x23) /* sb */,
959*22dc650dSSadaf Ebrahimi /* s b l */ F3(0x0) | OPC(0x3) /* lb */,
960*22dc650dSSadaf Ebrahimi /* s h s */ F3(0x1) | OPC(0x23) /* sh */,
961*22dc650dSSadaf Ebrahimi /* s h l */ F3(0x1) | OPC(0x3) /* lh */,
962*22dc650dSSadaf Ebrahimi /* s i s */ F3(0x2) | OPC(0x23) /* sw */,
963*22dc650dSSadaf Ebrahimi /* s i l */ F3(0x2) | OPC(0x3) /* lw */,
964*22dc650dSSadaf Ebrahimi 
965*22dc650dSSadaf Ebrahimi /* d   s */ F3(0x3) | OPC(0x27) /* fsd */,
966*22dc650dSSadaf Ebrahimi /* d   l */ F3(0x3) | OPC(0x7) /* fld */,
967*22dc650dSSadaf Ebrahimi /* s   s */ F3(0x2) | OPC(0x27) /* fsw */,
968*22dc650dSSadaf Ebrahimi /* s   l */ F3(0x2) | OPC(0x7) /* flw */,
969*22dc650dSSadaf Ebrahimi };
970*22dc650dSSadaf Ebrahimi 
971*22dc650dSSadaf Ebrahimi #undef ARCH_32_64
972*22dc650dSSadaf Ebrahimi 
push_mem_inst(struct sljit_compiler * compiler,sljit_s32 flags,sljit_s32 reg,sljit_s32 base,sljit_sw offset)973*22dc650dSSadaf Ebrahimi static sljit_s32 push_mem_inst(struct sljit_compiler *compiler, sljit_s32 flags, sljit_s32 reg, sljit_s32 base, sljit_sw offset)
974*22dc650dSSadaf Ebrahimi {
975*22dc650dSSadaf Ebrahimi 	sljit_ins ins;
976*22dc650dSSadaf Ebrahimi 
977*22dc650dSSadaf Ebrahimi 	SLJIT_ASSERT(FAST_IS_REG(base) && offset <= 0xfff && offset >= SIMM_MIN);
978*22dc650dSSadaf Ebrahimi 
979*22dc650dSSadaf Ebrahimi 	ins = data_transfer_insts[flags & MEM_MASK] | RS1(base);
980*22dc650dSSadaf Ebrahimi 	if (flags & LOAD_DATA)
981*22dc650dSSadaf Ebrahimi 		ins |= ((flags & MEM_MASK) <= GPR_REG ? RD(reg) : FRD(reg)) | IMM_I(offset);
982*22dc650dSSadaf Ebrahimi 	else
983*22dc650dSSadaf Ebrahimi 		ins |= ((flags & MEM_MASK) <= GPR_REG ? RS2(reg) : FRS2(reg)) | IMM_S(offset);
984*22dc650dSSadaf Ebrahimi 
985*22dc650dSSadaf Ebrahimi 	return push_inst(compiler, ins);
986*22dc650dSSadaf Ebrahimi }
987*22dc650dSSadaf Ebrahimi 
988*22dc650dSSadaf Ebrahimi /* Can perform an operation using at most 1 instruction. */
getput_arg_fast(struct sljit_compiler * compiler,sljit_s32 flags,sljit_s32 reg,sljit_s32 arg,sljit_sw argw)989*22dc650dSSadaf Ebrahimi static sljit_s32 getput_arg_fast(struct sljit_compiler *compiler, sljit_s32 flags, sljit_s32 reg, sljit_s32 arg, sljit_sw argw)
990*22dc650dSSadaf Ebrahimi {
991*22dc650dSSadaf Ebrahimi 	SLJIT_ASSERT(arg & SLJIT_MEM);
992*22dc650dSSadaf Ebrahimi 
993*22dc650dSSadaf Ebrahimi 	if (!(arg & OFFS_REG_MASK) && argw <= SIMM_MAX && argw >= SIMM_MIN) {
994*22dc650dSSadaf Ebrahimi 		/* Works for both absoulte and relative addresses. */
995*22dc650dSSadaf Ebrahimi 		if (SLJIT_UNLIKELY(flags & ARG_TEST))
996*22dc650dSSadaf Ebrahimi 			return 1;
997*22dc650dSSadaf Ebrahimi 
998*22dc650dSSadaf Ebrahimi 		FAIL_IF(push_mem_inst(compiler, flags, reg, arg & REG_MASK, argw));
999*22dc650dSSadaf Ebrahimi 		return -1;
1000*22dc650dSSadaf Ebrahimi 	}
1001*22dc650dSSadaf Ebrahimi 	return 0;
1002*22dc650dSSadaf Ebrahimi }
1003*22dc650dSSadaf Ebrahimi 
1004*22dc650dSSadaf Ebrahimi #define TO_ARGW_HI(argw) (((argw) & ~0xfff) + (((argw) & 0x800) ? 0x1000 : 0))
1005*22dc650dSSadaf Ebrahimi 
1006*22dc650dSSadaf Ebrahimi /* See getput_arg below.
1007*22dc650dSSadaf Ebrahimi    Note: can_cache is called only for binary operators. */
can_cache(sljit_s32 arg,sljit_sw argw,sljit_s32 next_arg,sljit_sw next_argw)1008*22dc650dSSadaf Ebrahimi static sljit_s32 can_cache(sljit_s32 arg, sljit_sw argw, sljit_s32 next_arg, sljit_sw next_argw)
1009*22dc650dSSadaf Ebrahimi {
1010*22dc650dSSadaf Ebrahimi 	SLJIT_ASSERT((arg & SLJIT_MEM) && (next_arg & SLJIT_MEM));
1011*22dc650dSSadaf Ebrahimi 
1012*22dc650dSSadaf Ebrahimi 	/* Simple operation except for updates. */
1013*22dc650dSSadaf Ebrahimi 	if (arg & OFFS_REG_MASK) {
1014*22dc650dSSadaf Ebrahimi 		argw &= 0x3;
1015*22dc650dSSadaf Ebrahimi 		next_argw &= 0x3;
1016*22dc650dSSadaf Ebrahimi 		if (argw && argw == next_argw && (arg == next_arg || (arg & OFFS_REG_MASK) == (next_arg & OFFS_REG_MASK)))
1017*22dc650dSSadaf Ebrahimi 			return 1;
1018*22dc650dSSadaf Ebrahimi 		return 0;
1019*22dc650dSSadaf Ebrahimi 	}
1020*22dc650dSSadaf Ebrahimi 
1021*22dc650dSSadaf Ebrahimi 	if (arg == next_arg) {
1022*22dc650dSSadaf Ebrahimi 		if (((next_argw - argw) <= SIMM_MAX && (next_argw - argw) >= SIMM_MIN)
1023*22dc650dSSadaf Ebrahimi 				|| TO_ARGW_HI(argw) == TO_ARGW_HI(next_argw))
1024*22dc650dSSadaf Ebrahimi 			return 1;
1025*22dc650dSSadaf Ebrahimi 		return 0;
1026*22dc650dSSadaf Ebrahimi 	}
1027*22dc650dSSadaf Ebrahimi 
1028*22dc650dSSadaf Ebrahimi 	return 0;
1029*22dc650dSSadaf Ebrahimi }
1030*22dc650dSSadaf Ebrahimi 
1031*22dc650dSSadaf Ebrahimi /* Emit the necessary instructions. See can_cache above. */
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)1032*22dc650dSSadaf Ebrahimi 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)
1033*22dc650dSSadaf Ebrahimi {
1034*22dc650dSSadaf Ebrahimi 	sljit_s32 base = arg & REG_MASK;
1035*22dc650dSSadaf Ebrahimi 	sljit_s32 tmp_r = (flags & MEM_USE_TMP2) ? TMP_REG2 : TMP_REG1;
1036*22dc650dSSadaf Ebrahimi 	sljit_sw offset, argw_hi;
1037*22dc650dSSadaf Ebrahimi 
1038*22dc650dSSadaf Ebrahimi 	SLJIT_ASSERT(arg & SLJIT_MEM);
1039*22dc650dSSadaf Ebrahimi 	if (!(next_arg & SLJIT_MEM)) {
1040*22dc650dSSadaf Ebrahimi 		next_arg = 0;
1041*22dc650dSSadaf Ebrahimi 		next_argw = 0;
1042*22dc650dSSadaf Ebrahimi 	}
1043*22dc650dSSadaf Ebrahimi 
1044*22dc650dSSadaf Ebrahimi 	if (SLJIT_UNLIKELY(arg & OFFS_REG_MASK)) {
1045*22dc650dSSadaf Ebrahimi 		argw &= 0x3;
1046*22dc650dSSadaf Ebrahimi 
1047*22dc650dSSadaf Ebrahimi 		/* Using the cache. */
1048*22dc650dSSadaf Ebrahimi 		if (argw == compiler->cache_argw) {
1049*22dc650dSSadaf Ebrahimi 			if (arg == compiler->cache_arg)
1050*22dc650dSSadaf Ebrahimi 				return push_mem_inst(compiler, flags, reg, TMP_REG3, 0);
1051*22dc650dSSadaf Ebrahimi 
1052*22dc650dSSadaf Ebrahimi 			if ((SLJIT_MEM | (arg & OFFS_REG_MASK)) == compiler->cache_arg) {
1053*22dc650dSSadaf Ebrahimi 				if (arg == next_arg && argw == (next_argw & 0x3)) {
1054*22dc650dSSadaf Ebrahimi 					compiler->cache_arg = arg;
1055*22dc650dSSadaf Ebrahimi 					compiler->cache_argw = argw;
1056*22dc650dSSadaf Ebrahimi 					FAIL_IF(push_inst(compiler, ADD | RD(TMP_REG3) | RS1(TMP_REG3) | RS2(base)));
1057*22dc650dSSadaf Ebrahimi 					return push_mem_inst(compiler, flags, reg, TMP_REG3, 0);
1058*22dc650dSSadaf Ebrahimi 				}
1059*22dc650dSSadaf Ebrahimi 				FAIL_IF(push_inst(compiler, ADD | RD(tmp_r) | RS1(base) | RS2(TMP_REG3)));
1060*22dc650dSSadaf Ebrahimi 				return push_mem_inst(compiler, flags, reg, tmp_r, 0);
1061*22dc650dSSadaf Ebrahimi 			}
1062*22dc650dSSadaf Ebrahimi 		}
1063*22dc650dSSadaf Ebrahimi 
1064*22dc650dSSadaf Ebrahimi 		if (SLJIT_UNLIKELY(argw)) {
1065*22dc650dSSadaf Ebrahimi 			compiler->cache_arg = SLJIT_MEM | (arg & OFFS_REG_MASK);
1066*22dc650dSSadaf Ebrahimi 			compiler->cache_argw = argw;
1067*22dc650dSSadaf Ebrahimi 			FAIL_IF(push_inst(compiler, SLLI | RD(TMP_REG3) | RS1(OFFS_REG(arg)) | IMM_I(argw)));
1068*22dc650dSSadaf Ebrahimi 		}
1069*22dc650dSSadaf Ebrahimi 
1070*22dc650dSSadaf Ebrahimi 		if (arg == next_arg && argw == (next_argw & 0x3)) {
1071*22dc650dSSadaf Ebrahimi 			compiler->cache_arg = arg;
1072*22dc650dSSadaf Ebrahimi 			compiler->cache_argw = argw;
1073*22dc650dSSadaf Ebrahimi 			FAIL_IF(push_inst(compiler, ADD | RD(TMP_REG3) | RS1(base) | RS2(!argw ? OFFS_REG(arg) : TMP_REG3)));
1074*22dc650dSSadaf Ebrahimi 			tmp_r = TMP_REG3;
1075*22dc650dSSadaf Ebrahimi 		}
1076*22dc650dSSadaf Ebrahimi 		else
1077*22dc650dSSadaf Ebrahimi 			FAIL_IF(push_inst(compiler, ADD | RD(tmp_r) | RS1(base) | RS2(!argw ? OFFS_REG(arg) : TMP_REG3)));
1078*22dc650dSSadaf Ebrahimi 		return push_mem_inst(compiler, flags, reg, tmp_r, 0);
1079*22dc650dSSadaf Ebrahimi 	}
1080*22dc650dSSadaf Ebrahimi 
1081*22dc650dSSadaf Ebrahimi 	if (compiler->cache_arg == arg && argw - compiler->cache_argw <= SIMM_MAX && argw - compiler->cache_argw >= SIMM_MIN)
1082*22dc650dSSadaf Ebrahimi 		return push_mem_inst(compiler, flags, reg, TMP_REG3, argw - compiler->cache_argw);
1083*22dc650dSSadaf Ebrahimi 
1084*22dc650dSSadaf Ebrahimi 	if (compiler->cache_arg == SLJIT_MEM && (argw - compiler->cache_argw <= SIMM_MAX) && (argw - compiler->cache_argw >= SIMM_MIN)) {
1085*22dc650dSSadaf Ebrahimi 		offset = argw - compiler->cache_argw;
1086*22dc650dSSadaf Ebrahimi 	} else {
1087*22dc650dSSadaf Ebrahimi 		compiler->cache_arg = SLJIT_MEM;
1088*22dc650dSSadaf Ebrahimi 
1089*22dc650dSSadaf Ebrahimi 		argw_hi = TO_ARGW_HI(argw);
1090*22dc650dSSadaf Ebrahimi 
1091*22dc650dSSadaf Ebrahimi 		if (next_arg && next_argw - argw <= SIMM_MAX && next_argw - argw >= SIMM_MIN && argw_hi != TO_ARGW_HI(next_argw)) {
1092*22dc650dSSadaf Ebrahimi 			FAIL_IF(load_immediate(compiler, TMP_REG3, argw, tmp_r));
1093*22dc650dSSadaf Ebrahimi 			compiler->cache_argw = argw;
1094*22dc650dSSadaf Ebrahimi 			offset = 0;
1095*22dc650dSSadaf Ebrahimi 		} else {
1096*22dc650dSSadaf Ebrahimi 			FAIL_IF(load_immediate(compiler, TMP_REG3, argw_hi, tmp_r));
1097*22dc650dSSadaf Ebrahimi 			compiler->cache_argw = argw_hi;
1098*22dc650dSSadaf Ebrahimi 			offset = argw & 0xfff;
1099*22dc650dSSadaf Ebrahimi 			argw = argw_hi;
1100*22dc650dSSadaf Ebrahimi 		}
1101*22dc650dSSadaf Ebrahimi 	}
1102*22dc650dSSadaf Ebrahimi 
1103*22dc650dSSadaf Ebrahimi 	if (!base)
1104*22dc650dSSadaf Ebrahimi 		return push_mem_inst(compiler, flags, reg, TMP_REG3, offset);
1105*22dc650dSSadaf Ebrahimi 
1106*22dc650dSSadaf Ebrahimi 	if (arg == next_arg && next_argw - argw <= SIMM_MAX && next_argw - argw >= SIMM_MIN) {
1107*22dc650dSSadaf Ebrahimi 		compiler->cache_arg = arg;
1108*22dc650dSSadaf Ebrahimi 		FAIL_IF(push_inst(compiler, ADD | RD(TMP_REG3) | RS1(TMP_REG3) | RS2(base)));
1109*22dc650dSSadaf Ebrahimi 		return push_mem_inst(compiler, flags, reg, TMP_REG3, offset);
1110*22dc650dSSadaf Ebrahimi 	}
1111*22dc650dSSadaf Ebrahimi 
1112*22dc650dSSadaf Ebrahimi 	FAIL_IF(push_inst(compiler, ADD | RD(tmp_r) | RS1(TMP_REG3) | RS2(base)));
1113*22dc650dSSadaf Ebrahimi 	return push_mem_inst(compiler, flags, reg, tmp_r, offset);
1114*22dc650dSSadaf Ebrahimi }
1115*22dc650dSSadaf Ebrahimi 
emit_op_mem(struct sljit_compiler * compiler,sljit_s32 flags,sljit_s32 reg,sljit_s32 arg,sljit_sw argw)1116*22dc650dSSadaf Ebrahimi static sljit_s32 emit_op_mem(struct sljit_compiler *compiler, sljit_s32 flags, sljit_s32 reg, sljit_s32 arg, sljit_sw argw)
1117*22dc650dSSadaf Ebrahimi {
1118*22dc650dSSadaf Ebrahimi 	sljit_s32 base = arg & REG_MASK;
1119*22dc650dSSadaf Ebrahimi 	sljit_s32 tmp_r = TMP_REG1;
1120*22dc650dSSadaf Ebrahimi 
1121*22dc650dSSadaf Ebrahimi 	if (getput_arg_fast(compiler, flags, reg, arg, argw))
1122*22dc650dSSadaf Ebrahimi 		return compiler->error;
1123*22dc650dSSadaf Ebrahimi 
1124*22dc650dSSadaf Ebrahimi 	if ((flags & MEM_MASK) <= GPR_REG && (flags & LOAD_DATA))
1125*22dc650dSSadaf Ebrahimi 		tmp_r = reg;
1126*22dc650dSSadaf Ebrahimi 
1127*22dc650dSSadaf Ebrahimi 	if (SLJIT_UNLIKELY(arg & OFFS_REG_MASK)) {
1128*22dc650dSSadaf Ebrahimi 		argw &= 0x3;
1129*22dc650dSSadaf Ebrahimi 
1130*22dc650dSSadaf Ebrahimi 		if (SLJIT_UNLIKELY(argw)) {
1131*22dc650dSSadaf Ebrahimi 			FAIL_IF(push_inst(compiler, SLLI | RD(tmp_r) | RS1(OFFS_REG(arg)) | IMM_I(argw)));
1132*22dc650dSSadaf Ebrahimi 			FAIL_IF(push_inst(compiler, ADD | RD(tmp_r) | RS1(tmp_r) | RS2(base)));
1133*22dc650dSSadaf Ebrahimi 		}
1134*22dc650dSSadaf Ebrahimi 		else
1135*22dc650dSSadaf Ebrahimi 			FAIL_IF(push_inst(compiler, ADD | RD(tmp_r) | RS1(base) | RS2(OFFS_REG(arg))));
1136*22dc650dSSadaf Ebrahimi 
1137*22dc650dSSadaf Ebrahimi 		argw = 0;
1138*22dc650dSSadaf Ebrahimi 	} else {
1139*22dc650dSSadaf Ebrahimi 		FAIL_IF(load_immediate(compiler, tmp_r, TO_ARGW_HI(argw), TMP_REG3));
1140*22dc650dSSadaf Ebrahimi 
1141*22dc650dSSadaf Ebrahimi 		if (base != 0)
1142*22dc650dSSadaf Ebrahimi 			FAIL_IF(push_inst(compiler, ADD | RD(tmp_r) | RS1(tmp_r) | RS2(base)));
1143*22dc650dSSadaf Ebrahimi 	}
1144*22dc650dSSadaf Ebrahimi 
1145*22dc650dSSadaf Ebrahimi 	return push_mem_inst(compiler, flags, reg, tmp_r, argw & 0xfff);
1146*22dc650dSSadaf Ebrahimi }
1147*22dc650dSSadaf Ebrahimi 
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)1148*22dc650dSSadaf Ebrahimi 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)
1149*22dc650dSSadaf Ebrahimi {
1150*22dc650dSSadaf Ebrahimi 	if (getput_arg_fast(compiler, flags, reg, arg1, arg1w))
1151*22dc650dSSadaf Ebrahimi 		return compiler->error;
1152*22dc650dSSadaf Ebrahimi 	return getput_arg(compiler, flags, reg, arg1, arg1w, arg2, arg2w);
1153*22dc650dSSadaf Ebrahimi }
1154*22dc650dSSadaf Ebrahimi 
1155*22dc650dSSadaf Ebrahimi #if (defined SLJIT_CONFIG_RISCV_32 && SLJIT_CONFIG_RISCV_32)
1156*22dc650dSSadaf Ebrahimi #define WORD 0
1157*22dc650dSSadaf Ebrahimi #define WORD_32 0
1158*22dc650dSSadaf Ebrahimi #define IMM_EXTEND(v) (IMM_I(v))
1159*22dc650dSSadaf Ebrahimi #else /* !SLJIT_CONFIG_RISCV_32 */
1160*22dc650dSSadaf Ebrahimi #define WORD word
1161*22dc650dSSadaf Ebrahimi #define WORD_32 0x08
1162*22dc650dSSadaf Ebrahimi #define IMM_EXTEND(v) (IMM_I((op & SLJIT_32) ? (v) : (32 + (v))))
1163*22dc650dSSadaf Ebrahimi #endif /* SLJIT_CONFIG_RISCV_32 */
1164*22dc650dSSadaf Ebrahimi 
emit_clz_ctz(struct sljit_compiler * compiler,sljit_s32 op,sljit_s32 dst,sljit_sw src)1165*22dc650dSSadaf Ebrahimi static sljit_s32 emit_clz_ctz(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 dst, sljit_sw src)
1166*22dc650dSSadaf Ebrahimi {
1167*22dc650dSSadaf Ebrahimi 	sljit_s32 is_clz = (GET_OPCODE(op) == SLJIT_CLZ);
1168*22dc650dSSadaf Ebrahimi #if (defined SLJIT_CONFIG_RISCV_64 && SLJIT_CONFIG_RISCV_64)
1169*22dc650dSSadaf Ebrahimi 	sljit_ins word = (sljit_ins)(op & SLJIT_32) >> 5;
1170*22dc650dSSadaf Ebrahimi 	sljit_ins word_size = (op & SLJIT_32) ? 32 : 64;
1171*22dc650dSSadaf Ebrahimi #else /* !SLJIT_CONFIG_RISCV_64 */
1172*22dc650dSSadaf Ebrahimi 	sljit_ins word_size = 32;
1173*22dc650dSSadaf Ebrahimi #endif /* SLJIT_CONFIG_RISCV_64 */
1174*22dc650dSSadaf Ebrahimi 
1175*22dc650dSSadaf Ebrahimi 	SLJIT_ASSERT(WORD == 0 || WORD == 0x8);
1176*22dc650dSSadaf Ebrahimi 
1177*22dc650dSSadaf Ebrahimi 	/* The OTHER_FLAG is the counter. */
1178*22dc650dSSadaf Ebrahimi 	FAIL_IF(push_inst(compiler, ADDI | WORD | RD(OTHER_FLAG) | RS1(TMP_ZERO) | IMM_I(word_size)));
1179*22dc650dSSadaf Ebrahimi 
1180*22dc650dSSadaf Ebrahimi 	/* The TMP_REG2 is the next value. */
1181*22dc650dSSadaf Ebrahimi 	if (src != TMP_REG2)
1182*22dc650dSSadaf Ebrahimi 		FAIL_IF(push_inst(compiler, ADDI | WORD | RD(TMP_REG2) | RS1(src) | IMM_I(0)));
1183*22dc650dSSadaf Ebrahimi 
1184*22dc650dSSadaf Ebrahimi 	FAIL_IF(push_inst(compiler, BEQ | RS1(TMP_REG2) | RS2(TMP_ZERO) | ((sljit_ins)((is_clz ? 4 : 5) * SSIZE_OF(ins)) << 7) | ((sljit_ins)(8 * SSIZE_OF(ins)) << 20)));
1185*22dc650dSSadaf Ebrahimi 
1186*22dc650dSSadaf Ebrahimi 	FAIL_IF(push_inst(compiler, ADDI | WORD | RD(OTHER_FLAG) | RS1(TMP_ZERO) | IMM_I(0)));
1187*22dc650dSSadaf Ebrahimi 	if (!is_clz) {
1188*22dc650dSSadaf Ebrahimi 		FAIL_IF(push_inst(compiler, ANDI | RD(TMP_REG1) | RS1(TMP_REG2) | IMM_I(1)));
1189*22dc650dSSadaf Ebrahimi 		FAIL_IF(push_inst(compiler, BNE | RS1(TMP_REG1) | RS2(TMP_ZERO) | ((sljit_ins)(2 * SSIZE_OF(ins)) << 7) | ((sljit_ins)(8 * SSIZE_OF(ins)) << 20)));
1190*22dc650dSSadaf Ebrahimi 	} else
1191*22dc650dSSadaf Ebrahimi 		FAIL_IF(push_inst(compiler, BLT | RS1(TMP_REG2) | RS2(TMP_ZERO) | ((sljit_ins)(2 * SSIZE_OF(ins)) << 7) | ((sljit_ins)(8 * SSIZE_OF(ins)) << 20)));
1192*22dc650dSSadaf Ebrahimi 
1193*22dc650dSSadaf Ebrahimi 	/* The TMP_REG1 is the next shift. */
1194*22dc650dSSadaf Ebrahimi 	FAIL_IF(push_inst(compiler, ADDI | WORD | RD(TMP_REG1) | RS1(TMP_ZERO) | IMM_I(word_size)));
1195*22dc650dSSadaf Ebrahimi 
1196*22dc650dSSadaf Ebrahimi 	FAIL_IF(push_inst(compiler, ADDI | WORD | RD(EQUAL_FLAG) | RS1(TMP_REG2) | IMM_I(0)));
1197*22dc650dSSadaf Ebrahimi 	FAIL_IF(push_inst(compiler, SRLI | WORD | RD(TMP_REG1) | RS1(TMP_REG1) | IMM_I(1)));
1198*22dc650dSSadaf Ebrahimi 
1199*22dc650dSSadaf Ebrahimi 	FAIL_IF(push_inst(compiler, (is_clz ? SRL : SLL) | WORD | RD(TMP_REG2) | RS1(EQUAL_FLAG) | RS2(TMP_REG1)));
1200*22dc650dSSadaf Ebrahimi 	FAIL_IF(push_inst(compiler, BNE | RS1(TMP_REG2) | RS2(TMP_ZERO) | ((sljit_ins)0xfe000e80 - ((2 * SSIZE_OF(ins)) << 7))));
1201*22dc650dSSadaf Ebrahimi 	FAIL_IF(push_inst(compiler, ADDI | WORD | RD(TMP_REG2) | RS1(TMP_REG1) | IMM_I(-1)));
1202*22dc650dSSadaf Ebrahimi 	FAIL_IF(push_inst(compiler, (is_clz ? SRL : SLL) | WORD | RD(TMP_REG2) | RS1(EQUAL_FLAG) | RS2(TMP_REG2)));
1203*22dc650dSSadaf Ebrahimi 	FAIL_IF(push_inst(compiler, OR | RD(OTHER_FLAG) | RS1(OTHER_FLAG) | RS2(TMP_REG1)));
1204*22dc650dSSadaf Ebrahimi 	FAIL_IF(push_inst(compiler, BEQ | RS1(TMP_REG2) | RS2(TMP_ZERO) | ((sljit_ins)0xfe000e80 - ((5 * SSIZE_OF(ins)) << 7))));
1205*22dc650dSSadaf Ebrahimi 
1206*22dc650dSSadaf Ebrahimi 	return push_inst(compiler, ADDI | WORD | RD(dst) | RS1(OTHER_FLAG) | IMM_I(0));
1207*22dc650dSSadaf Ebrahimi }
1208*22dc650dSSadaf Ebrahimi 
emit_rev(struct sljit_compiler * compiler,sljit_s32 op,sljit_s32 dst,sljit_sw src)1209*22dc650dSSadaf Ebrahimi static sljit_s32 emit_rev(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 dst, sljit_sw src)
1210*22dc650dSSadaf Ebrahimi {
1211*22dc650dSSadaf Ebrahimi 	SLJIT_UNUSED_ARG(op);
1212*22dc650dSSadaf Ebrahimi 
1213*22dc650dSSadaf Ebrahimi #if (defined SLJIT_CONFIG_RISCV_64 && SLJIT_CONFIG_RISCV_64)
1214*22dc650dSSadaf Ebrahimi 	if (!(op & SLJIT_32)) {
1215*22dc650dSSadaf Ebrahimi 		FAIL_IF(push_inst(compiler, LUI | RD(OTHER_FLAG) | 0x10000));
1216*22dc650dSSadaf Ebrahimi 		FAIL_IF(push_inst(compiler, SRLI | RD(TMP_REG1) | RS1(src) | IMM_I(32)));
1217*22dc650dSSadaf Ebrahimi 		FAIL_IF(push_inst(compiler, ADDI | RD(OTHER_FLAG) | RS1(OTHER_FLAG) | IMM_I(0xfff)));
1218*22dc650dSSadaf Ebrahimi 		FAIL_IF(push_inst(compiler, SLLI | RD(dst) | RS1(src) | IMM_I(32)));
1219*22dc650dSSadaf Ebrahimi 		FAIL_IF(push_inst(compiler, SLLI | RD(EQUAL_FLAG) | RS1(OTHER_FLAG) | IMM_I(32)));
1220*22dc650dSSadaf Ebrahimi 		FAIL_IF(push_inst(compiler, OR | RD(dst) | RS1(dst) | RS2(TMP_REG1)));
1221*22dc650dSSadaf Ebrahimi 		FAIL_IF(push_inst(compiler, OR | RD(OTHER_FLAG) | RS1(OTHER_FLAG) | RS2(EQUAL_FLAG)));
1222*22dc650dSSadaf Ebrahimi 
1223*22dc650dSSadaf Ebrahimi 		FAIL_IF(push_inst(compiler, SRLI | RD(TMP_REG1) | RS1(dst) | IMM_I(16)));
1224*22dc650dSSadaf Ebrahimi 		FAIL_IF(push_inst(compiler, AND | RD(dst) | RS1(dst) | RS2(OTHER_FLAG)));
1225*22dc650dSSadaf Ebrahimi 		FAIL_IF(push_inst(compiler, AND | RD(TMP_REG1) | RS1(TMP_REG1) | RS2(OTHER_FLAG)));
1226*22dc650dSSadaf Ebrahimi 		FAIL_IF(push_inst(compiler, SLLI | RD(EQUAL_FLAG) | RS1(OTHER_FLAG) | IMM_I(8)));
1227*22dc650dSSadaf Ebrahimi 		FAIL_IF(push_inst(compiler, SLLI | RD(dst) | RS1(dst) | IMM_I(16)));
1228*22dc650dSSadaf Ebrahimi 		FAIL_IF(push_inst(compiler, XOR | RD(OTHER_FLAG) | RS1(OTHER_FLAG) | RS2(EQUAL_FLAG)));
1229*22dc650dSSadaf Ebrahimi 		FAIL_IF(push_inst(compiler, OR | RD(dst) | RS1(dst) | RS2(TMP_REG1)));
1230*22dc650dSSadaf Ebrahimi 
1231*22dc650dSSadaf Ebrahimi 		FAIL_IF(push_inst(compiler, SRLI | RD(TMP_REG1) | RS1(dst) | IMM_I(8)));
1232*22dc650dSSadaf Ebrahimi 		FAIL_IF(push_inst(compiler, AND | RD(dst) | RS1(dst) | RS2(OTHER_FLAG)));
1233*22dc650dSSadaf Ebrahimi 		FAIL_IF(push_inst(compiler, AND | RD(TMP_REG1) | RS1(TMP_REG1) | RS2(OTHER_FLAG)));
1234*22dc650dSSadaf Ebrahimi 		FAIL_IF(push_inst(compiler, SLLI | RD(dst) | RS1(dst) | IMM_I(8)));
1235*22dc650dSSadaf Ebrahimi 		return push_inst(compiler, OR | RD(dst) | RS1(dst) | RS2(TMP_REG1));
1236*22dc650dSSadaf Ebrahimi 	}
1237*22dc650dSSadaf Ebrahimi #endif /* SLJIT_CONFIG_RISCV_64 */
1238*22dc650dSSadaf Ebrahimi 
1239*22dc650dSSadaf Ebrahimi 	FAIL_IF(push_inst(compiler, SRLI | WORD_32 | RD(TMP_REG1) | RS1(src) | IMM_I(16)));
1240*22dc650dSSadaf Ebrahimi 	FAIL_IF(push_inst(compiler, LUI | RD(OTHER_FLAG) | 0xff0000));
1241*22dc650dSSadaf Ebrahimi 	FAIL_IF(push_inst(compiler, SLLI | WORD_32 | RD(dst) | RS1(src) | IMM_I(16)));
1242*22dc650dSSadaf Ebrahimi 	FAIL_IF(push_inst(compiler, ORI | RD(OTHER_FLAG) | RS1(OTHER_FLAG) | IMM_I(0xff)));
1243*22dc650dSSadaf Ebrahimi 	FAIL_IF(push_inst(compiler, OR | RD(dst) | RS1(dst) | RS2(TMP_REG1)));
1244*22dc650dSSadaf Ebrahimi 
1245*22dc650dSSadaf Ebrahimi 	FAIL_IF(push_inst(compiler, SRLI | WORD_32 | RD(TMP_REG1) | RS1(dst) | IMM_I(8)));
1246*22dc650dSSadaf Ebrahimi 	FAIL_IF(push_inst(compiler, AND | RD(dst) | RS1(dst) | RS2(OTHER_FLAG)));
1247*22dc650dSSadaf Ebrahimi 	FAIL_IF(push_inst(compiler, AND | RD(TMP_REG1) | RS1(TMP_REG1) | RS2(OTHER_FLAG)));
1248*22dc650dSSadaf Ebrahimi 	FAIL_IF(push_inst(compiler, SLLI | WORD_32 | RD(dst) | RS1(dst) | IMM_I(8)));
1249*22dc650dSSadaf Ebrahimi 	return push_inst(compiler, OR | RD(dst) | RS1(dst) | RS2(TMP_REG1));
1250*22dc650dSSadaf Ebrahimi }
1251*22dc650dSSadaf Ebrahimi 
emit_rev16(struct sljit_compiler * compiler,sljit_s32 op,sljit_s32 dst,sljit_sw src)1252*22dc650dSSadaf Ebrahimi static sljit_s32 emit_rev16(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 dst, sljit_sw src)
1253*22dc650dSSadaf Ebrahimi {
1254*22dc650dSSadaf Ebrahimi #if (defined SLJIT_CONFIG_RISCV_64 && SLJIT_CONFIG_RISCV_64)
1255*22dc650dSSadaf Ebrahimi 	sljit_ins word = (sljit_ins)(op & SLJIT_32) >> 5;
1256*22dc650dSSadaf Ebrahimi 	sljit_ins word_size = (op & SLJIT_32) ? 32 : 64;
1257*22dc650dSSadaf Ebrahimi #else /* !SLJIT_CONFIG_RISCV_64 */
1258*22dc650dSSadaf Ebrahimi 	sljit_ins word_size = 32;
1259*22dc650dSSadaf Ebrahimi #endif /* SLJIT_CONFIG_RISCV_64 */
1260*22dc650dSSadaf Ebrahimi 
1261*22dc650dSSadaf Ebrahimi 	FAIL_IF(push_inst(compiler, SRLI | WORD | RD(TMP_REG1) | RS1(src) | IMM_I(8)));
1262*22dc650dSSadaf Ebrahimi 	FAIL_IF(push_inst(compiler, SLLI | WORD | RD(dst) | RS1(src) | IMM_I(word_size - 8)));
1263*22dc650dSSadaf Ebrahimi 	FAIL_IF(push_inst(compiler, ANDI | RD(TMP_REG1) | RS1(TMP_REG1) | IMM_I(0xff)));
1264*22dc650dSSadaf Ebrahimi 	FAIL_IF(push_inst(compiler, (GET_OPCODE(op) == SLJIT_REV_U16 ? SRLI : SRAI) | WORD | RD(dst) | RS1(dst) | IMM_I(word_size - 16)));
1265*22dc650dSSadaf Ebrahimi 	return push_inst(compiler, OR | RD(dst) | RS1(dst) | RS2(TMP_REG1));
1266*22dc650dSSadaf Ebrahimi }
1267*22dc650dSSadaf Ebrahimi 
1268*22dc650dSSadaf Ebrahimi #define EMIT_LOGICAL(op_imm, op_reg) \
1269*22dc650dSSadaf Ebrahimi 	if (flags & SRC2_IMM) { \
1270*22dc650dSSadaf Ebrahimi 		if (op & SLJIT_SET_Z) \
1271*22dc650dSSadaf Ebrahimi 			FAIL_IF(push_inst(compiler, op_imm | RD(EQUAL_FLAG) | RS1(src1) | IMM_I(src2))); \
1272*22dc650dSSadaf Ebrahimi 		if (!(flags & UNUSED_DEST)) \
1273*22dc650dSSadaf Ebrahimi 			FAIL_IF(push_inst(compiler, op_imm | RD(dst) | RS1(src1) | IMM_I(src2))); \
1274*22dc650dSSadaf Ebrahimi 	} \
1275*22dc650dSSadaf Ebrahimi 	else { \
1276*22dc650dSSadaf Ebrahimi 		if (op & SLJIT_SET_Z) \
1277*22dc650dSSadaf Ebrahimi 			FAIL_IF(push_inst(compiler, op_reg | RD(EQUAL_FLAG) | RS1(src1) | RS2(src2))); \
1278*22dc650dSSadaf Ebrahimi 		if (!(flags & UNUSED_DEST)) \
1279*22dc650dSSadaf Ebrahimi 			FAIL_IF(push_inst(compiler, op_reg | RD(dst) | RS1(src1) | RS2(src2))); \
1280*22dc650dSSadaf Ebrahimi 	}
1281*22dc650dSSadaf Ebrahimi 
1282*22dc650dSSadaf Ebrahimi #define EMIT_SHIFT(imm, reg) \
1283*22dc650dSSadaf Ebrahimi 	op_imm = (imm); \
1284*22dc650dSSadaf Ebrahimi 	op_reg = (reg);
1285*22dc650dSSadaf Ebrahimi 
emit_single_op(struct sljit_compiler * compiler,sljit_s32 op,sljit_s32 flags,sljit_s32 dst,sljit_s32 src1,sljit_sw src2)1286*22dc650dSSadaf Ebrahimi static SLJIT_INLINE sljit_s32 emit_single_op(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 flags,
1287*22dc650dSSadaf Ebrahimi 	sljit_s32 dst, sljit_s32 src1, sljit_sw src2)
1288*22dc650dSSadaf Ebrahimi {
1289*22dc650dSSadaf Ebrahimi 	sljit_s32 is_overflow, is_carry, carry_src_r, is_handled, reg;
1290*22dc650dSSadaf Ebrahimi 	sljit_ins op_imm, op_reg;
1291*22dc650dSSadaf Ebrahimi #if (defined SLJIT_CONFIG_RISCV_64 && SLJIT_CONFIG_RISCV_64)
1292*22dc650dSSadaf Ebrahimi 	sljit_ins word = (sljit_ins)(op & SLJIT_32) >> 5;
1293*22dc650dSSadaf Ebrahimi #endif /* SLJIT_CONFIG_RISCV_64 */
1294*22dc650dSSadaf Ebrahimi 
1295*22dc650dSSadaf Ebrahimi 	SLJIT_ASSERT(WORD == 0 || WORD == 0x8);
1296*22dc650dSSadaf Ebrahimi 
1297*22dc650dSSadaf Ebrahimi 	switch (GET_OPCODE(op)) {
1298*22dc650dSSadaf Ebrahimi 	case SLJIT_MOV:
1299*22dc650dSSadaf Ebrahimi 		SLJIT_ASSERT(src1 == TMP_ZERO && !(flags & SRC2_IMM));
1300*22dc650dSSadaf Ebrahimi 		if (dst != src2)
1301*22dc650dSSadaf Ebrahimi 			return push_inst(compiler, ADDI | RD(dst) | RS1(src2) | IMM_I(0));
1302*22dc650dSSadaf Ebrahimi 		return SLJIT_SUCCESS;
1303*22dc650dSSadaf Ebrahimi 
1304*22dc650dSSadaf Ebrahimi 	case SLJIT_MOV_U8:
1305*22dc650dSSadaf Ebrahimi 		SLJIT_ASSERT(src1 == TMP_ZERO && !(flags & SRC2_IMM));
1306*22dc650dSSadaf Ebrahimi 		if ((flags & (REG_DEST | REG2_SOURCE)) == (REG_DEST | REG2_SOURCE))
1307*22dc650dSSadaf Ebrahimi 			return push_inst(compiler, ANDI | RD(dst) | RS1(src2) | IMM_I(0xff));
1308*22dc650dSSadaf Ebrahimi 		SLJIT_ASSERT(dst == src2);
1309*22dc650dSSadaf Ebrahimi 		return SLJIT_SUCCESS;
1310*22dc650dSSadaf Ebrahimi 
1311*22dc650dSSadaf Ebrahimi 	case SLJIT_MOV_S8:
1312*22dc650dSSadaf Ebrahimi 		SLJIT_ASSERT(src1 == TMP_ZERO && !(flags & SRC2_IMM));
1313*22dc650dSSadaf Ebrahimi 		if ((flags & (REG_DEST | REG2_SOURCE)) == (REG_DEST | REG2_SOURCE)) {
1314*22dc650dSSadaf Ebrahimi 			FAIL_IF(push_inst(compiler, SLLI | WORD | RD(dst) | RS1(src2) | IMM_EXTEND(24)));
1315*22dc650dSSadaf Ebrahimi 			return push_inst(compiler, SRAI | WORD | RD(dst) | RS1(dst) | IMM_EXTEND(24));
1316*22dc650dSSadaf Ebrahimi 		}
1317*22dc650dSSadaf Ebrahimi 		SLJIT_ASSERT(dst == src2);
1318*22dc650dSSadaf Ebrahimi 		return SLJIT_SUCCESS;
1319*22dc650dSSadaf Ebrahimi 
1320*22dc650dSSadaf Ebrahimi 	case SLJIT_MOV_U16:
1321*22dc650dSSadaf Ebrahimi 		SLJIT_ASSERT(src1 == TMP_ZERO && !(flags & SRC2_IMM));
1322*22dc650dSSadaf Ebrahimi 		if ((flags & (REG_DEST | REG2_SOURCE)) == (REG_DEST | REG2_SOURCE)) {
1323*22dc650dSSadaf Ebrahimi 			FAIL_IF(push_inst(compiler, SLLI | WORD | RD(dst) | RS1(src2) | IMM_EXTEND(16)));
1324*22dc650dSSadaf Ebrahimi 			return push_inst(compiler, SRLI | WORD | RD(dst) | RS1(dst) | IMM_EXTEND(16));
1325*22dc650dSSadaf Ebrahimi 		}
1326*22dc650dSSadaf Ebrahimi 		SLJIT_ASSERT(dst == src2);
1327*22dc650dSSadaf Ebrahimi 		return SLJIT_SUCCESS;
1328*22dc650dSSadaf Ebrahimi 
1329*22dc650dSSadaf Ebrahimi 	case SLJIT_MOV_S16:
1330*22dc650dSSadaf Ebrahimi 		SLJIT_ASSERT(src1 == TMP_ZERO && !(flags & SRC2_IMM));
1331*22dc650dSSadaf Ebrahimi 		if ((flags & (REG_DEST | REG2_SOURCE)) == (REG_DEST | REG2_SOURCE)) {
1332*22dc650dSSadaf Ebrahimi 			FAIL_IF(push_inst(compiler, SLLI | WORD | RD(dst) | RS1(src2) | IMM_EXTEND(16)));
1333*22dc650dSSadaf Ebrahimi 			return push_inst(compiler, SRAI | WORD | RD(dst) | RS1(dst) | IMM_EXTEND(16));
1334*22dc650dSSadaf Ebrahimi 		}
1335*22dc650dSSadaf Ebrahimi 		SLJIT_ASSERT(dst == src2);
1336*22dc650dSSadaf Ebrahimi 		return SLJIT_SUCCESS;
1337*22dc650dSSadaf Ebrahimi 
1338*22dc650dSSadaf Ebrahimi #if (defined SLJIT_CONFIG_RISCV_64 && SLJIT_CONFIG_RISCV_64)
1339*22dc650dSSadaf Ebrahimi 	case SLJIT_MOV_U32:
1340*22dc650dSSadaf Ebrahimi 		SLJIT_ASSERT(src1 == TMP_ZERO && !(flags & SRC2_IMM));
1341*22dc650dSSadaf Ebrahimi 		if ((flags & (REG_DEST | REG2_SOURCE)) == (REG_DEST | REG2_SOURCE)) {
1342*22dc650dSSadaf Ebrahimi 			FAIL_IF(push_inst(compiler, SLLI | RD(dst) | RS1(src2) | IMM_I(32)));
1343*22dc650dSSadaf Ebrahimi 			return push_inst(compiler, SRLI | RD(dst) | RS1(dst) | IMM_I(32));
1344*22dc650dSSadaf Ebrahimi 		}
1345*22dc650dSSadaf Ebrahimi 		SLJIT_ASSERT(dst == src2);
1346*22dc650dSSadaf Ebrahimi 		return SLJIT_SUCCESS;
1347*22dc650dSSadaf Ebrahimi 
1348*22dc650dSSadaf Ebrahimi 	case SLJIT_MOV_S32:
1349*22dc650dSSadaf Ebrahimi 		SLJIT_ASSERT(src1 == TMP_ZERO && !(flags & SRC2_IMM));
1350*22dc650dSSadaf Ebrahimi 		if ((flags & (REG_DEST | REG2_SOURCE)) == (REG_DEST | REG2_SOURCE))
1351*22dc650dSSadaf Ebrahimi 			return push_inst(compiler, ADDI | 0x8 | RD(dst) | RS1(src2) | IMM_I(0));
1352*22dc650dSSadaf Ebrahimi 		SLJIT_ASSERT(dst == src2);
1353*22dc650dSSadaf Ebrahimi 		return SLJIT_SUCCESS;
1354*22dc650dSSadaf Ebrahimi #endif /* SLJIT_CONFIG_RISCV_64 */
1355*22dc650dSSadaf Ebrahimi 
1356*22dc650dSSadaf Ebrahimi 	case SLJIT_CLZ:
1357*22dc650dSSadaf Ebrahimi 	case SLJIT_CTZ:
1358*22dc650dSSadaf Ebrahimi 		SLJIT_ASSERT(src1 == TMP_ZERO && !(flags & SRC2_IMM));
1359*22dc650dSSadaf Ebrahimi 		return emit_clz_ctz(compiler, op, dst, src2);
1360*22dc650dSSadaf Ebrahimi 
1361*22dc650dSSadaf Ebrahimi 	case SLJIT_REV:
1362*22dc650dSSadaf Ebrahimi 	case SLJIT_REV_S32:
1363*22dc650dSSadaf Ebrahimi #if (defined SLJIT_CONFIG_RISCV_32 && SLJIT_CONFIG_RISCV_32)
1364*22dc650dSSadaf Ebrahimi 	case SLJIT_REV_U32:
1365*22dc650dSSadaf Ebrahimi #endif /* SLJIT_CONFIG_RISCV_32 */
1366*22dc650dSSadaf Ebrahimi 		SLJIT_ASSERT(src1 == TMP_ZERO && !(flags & SRC2_IMM));
1367*22dc650dSSadaf Ebrahimi 		return emit_rev(compiler, op, dst, src2);
1368*22dc650dSSadaf Ebrahimi 
1369*22dc650dSSadaf Ebrahimi 	case SLJIT_REV_U16:
1370*22dc650dSSadaf Ebrahimi 	case SLJIT_REV_S16:
1371*22dc650dSSadaf Ebrahimi 		SLJIT_ASSERT(src1 == TMP_ZERO && !(flags & SRC2_IMM));
1372*22dc650dSSadaf Ebrahimi 		return emit_rev16(compiler, op, dst, src2);
1373*22dc650dSSadaf Ebrahimi 
1374*22dc650dSSadaf Ebrahimi #if (defined SLJIT_CONFIG_RISCV_64 && SLJIT_CONFIG_RISCV_64)
1375*22dc650dSSadaf Ebrahimi 	case SLJIT_REV_U32:
1376*22dc650dSSadaf Ebrahimi 		SLJIT_ASSERT(src1 == TMP_ZERO && !(flags & SRC2_IMM) && dst != TMP_REG1);
1377*22dc650dSSadaf Ebrahimi 		FAIL_IF(emit_rev(compiler, op, dst, src2));
1378*22dc650dSSadaf Ebrahimi 		if (dst == TMP_REG2)
1379*22dc650dSSadaf Ebrahimi 			return SLJIT_SUCCESS;
1380*22dc650dSSadaf Ebrahimi 		FAIL_IF(push_inst(compiler, SLLI | RD(dst) | RS1(dst) | IMM_I(32)));
1381*22dc650dSSadaf Ebrahimi 		return push_inst(compiler, SRLI | RD(dst) | RS1(dst) | IMM_I(32));
1382*22dc650dSSadaf Ebrahimi #endif /* SLJIT_CONFIG_RISCV_32 */
1383*22dc650dSSadaf Ebrahimi 
1384*22dc650dSSadaf Ebrahimi 	case SLJIT_ADD:
1385*22dc650dSSadaf Ebrahimi 		/* Overflow computation (both add and sub): overflow = src1_sign ^ src2_sign ^ result_sign ^ carry_flag */
1386*22dc650dSSadaf Ebrahimi 		is_overflow = GET_FLAG_TYPE(op) == SLJIT_OVERFLOW;
1387*22dc650dSSadaf Ebrahimi 		carry_src_r = GET_FLAG_TYPE(op) == SLJIT_CARRY;
1388*22dc650dSSadaf Ebrahimi 
1389*22dc650dSSadaf Ebrahimi 		if (flags & SRC2_IMM) {
1390*22dc650dSSadaf Ebrahimi 			if (is_overflow) {
1391*22dc650dSSadaf Ebrahimi 				if (src2 >= 0)
1392*22dc650dSSadaf Ebrahimi 					FAIL_IF(push_inst(compiler, ADDI | RD(EQUAL_FLAG) | RS1(src1) | IMM_I(0)));
1393*22dc650dSSadaf Ebrahimi 				else
1394*22dc650dSSadaf Ebrahimi 					FAIL_IF(push_inst(compiler, XORI | RD(EQUAL_FLAG) | RS1(src1) | IMM_I(-1)));
1395*22dc650dSSadaf Ebrahimi 			}
1396*22dc650dSSadaf Ebrahimi 			else if (op & SLJIT_SET_Z)
1397*22dc650dSSadaf Ebrahimi 				FAIL_IF(push_inst(compiler, ADDI | WORD | RD(EQUAL_FLAG) | RS1(src1) | IMM_I(src2)));
1398*22dc650dSSadaf Ebrahimi 
1399*22dc650dSSadaf Ebrahimi 			/* Only the zero flag is needed. */
1400*22dc650dSSadaf Ebrahimi 			if (!(flags & UNUSED_DEST) || (op & VARIABLE_FLAG_MASK))
1401*22dc650dSSadaf Ebrahimi 				FAIL_IF(push_inst(compiler, ADDI | WORD | RD(dst) | RS1(src1) | IMM_I(src2)));
1402*22dc650dSSadaf Ebrahimi 		}
1403*22dc650dSSadaf Ebrahimi 		else {
1404*22dc650dSSadaf Ebrahimi 			if (is_overflow)
1405*22dc650dSSadaf Ebrahimi 				FAIL_IF(push_inst(compiler, XOR | RD(EQUAL_FLAG) | RS1(src1) | RS2(src2)));
1406*22dc650dSSadaf Ebrahimi 			else if (op & SLJIT_SET_Z)
1407*22dc650dSSadaf Ebrahimi 				FAIL_IF(push_inst(compiler, ADD | WORD | RD(EQUAL_FLAG) | RS1(src1) | RS2(src2)));
1408*22dc650dSSadaf Ebrahimi 
1409*22dc650dSSadaf Ebrahimi 			if (is_overflow || carry_src_r != 0) {
1410*22dc650dSSadaf Ebrahimi 				if (src1 != dst)
1411*22dc650dSSadaf Ebrahimi 					carry_src_r = (sljit_s32)src1;
1412*22dc650dSSadaf Ebrahimi 				else if (src2 != dst)
1413*22dc650dSSadaf Ebrahimi 					carry_src_r = (sljit_s32)src2;
1414*22dc650dSSadaf Ebrahimi 				else {
1415*22dc650dSSadaf Ebrahimi 					FAIL_IF(push_inst(compiler, ADDI | RD(OTHER_FLAG) | RS1(src1) | IMM_I(0)));
1416*22dc650dSSadaf Ebrahimi 					carry_src_r = OTHER_FLAG;
1417*22dc650dSSadaf Ebrahimi 				}
1418*22dc650dSSadaf Ebrahimi 			}
1419*22dc650dSSadaf Ebrahimi 
1420*22dc650dSSadaf Ebrahimi 			/* Only the zero flag is needed. */
1421*22dc650dSSadaf Ebrahimi 			if (!(flags & UNUSED_DEST) || (op & VARIABLE_FLAG_MASK))
1422*22dc650dSSadaf Ebrahimi 				FAIL_IF(push_inst(compiler, ADD | WORD | RD(dst) | RS1(src1) | RS2(src2)));
1423*22dc650dSSadaf Ebrahimi 		}
1424*22dc650dSSadaf Ebrahimi 
1425*22dc650dSSadaf Ebrahimi 		/* Carry is zero if a + b >= a or a + b >= b, otherwise it is 1. */
1426*22dc650dSSadaf Ebrahimi 		if (is_overflow || carry_src_r != 0) {
1427*22dc650dSSadaf Ebrahimi 			if (flags & SRC2_IMM)
1428*22dc650dSSadaf Ebrahimi 				FAIL_IF(push_inst(compiler, SLTUI | RD(OTHER_FLAG) | RS1(dst) | IMM_I(src2)));
1429*22dc650dSSadaf Ebrahimi 			else
1430*22dc650dSSadaf Ebrahimi 				FAIL_IF(push_inst(compiler, SLTU | RD(OTHER_FLAG) | RS1(dst) | RS2(carry_src_r)));
1431*22dc650dSSadaf Ebrahimi 		}
1432*22dc650dSSadaf Ebrahimi 
1433*22dc650dSSadaf Ebrahimi 		if (!is_overflow)
1434*22dc650dSSadaf Ebrahimi 			return SLJIT_SUCCESS;
1435*22dc650dSSadaf Ebrahimi 
1436*22dc650dSSadaf Ebrahimi 		FAIL_IF(push_inst(compiler, XOR | RD(TMP_REG1) | RS1(dst) | RS2(EQUAL_FLAG)));
1437*22dc650dSSadaf Ebrahimi 		if (op & SLJIT_SET_Z)
1438*22dc650dSSadaf Ebrahimi 			FAIL_IF(push_inst(compiler, ADDI | RD(EQUAL_FLAG) | RS1(dst) | IMM_I(0)));
1439*22dc650dSSadaf Ebrahimi 		FAIL_IF(push_inst(compiler, SRLI | WORD | RD(TMP_REG1) | RS1(TMP_REG1) | IMM_EXTEND(31)));
1440*22dc650dSSadaf Ebrahimi 		return push_inst(compiler, XOR | RD(OTHER_FLAG) | RS1(TMP_REG1) | RS2(OTHER_FLAG));
1441*22dc650dSSadaf Ebrahimi 
1442*22dc650dSSadaf Ebrahimi 	case SLJIT_ADDC:
1443*22dc650dSSadaf Ebrahimi 		carry_src_r = GET_FLAG_TYPE(op) == SLJIT_CARRY;
1444*22dc650dSSadaf Ebrahimi 
1445*22dc650dSSadaf Ebrahimi 		if (flags & SRC2_IMM) {
1446*22dc650dSSadaf Ebrahimi 			FAIL_IF(push_inst(compiler, ADDI | WORD | RD(dst) | RS1(src1) | IMM_I(src2)));
1447*22dc650dSSadaf Ebrahimi 		} else {
1448*22dc650dSSadaf Ebrahimi 			if (carry_src_r != 0) {
1449*22dc650dSSadaf Ebrahimi 				if (src1 != dst)
1450*22dc650dSSadaf Ebrahimi 					carry_src_r = (sljit_s32)src1;
1451*22dc650dSSadaf Ebrahimi 				else if (src2 != dst)
1452*22dc650dSSadaf Ebrahimi 					carry_src_r = (sljit_s32)src2;
1453*22dc650dSSadaf Ebrahimi 				else {
1454*22dc650dSSadaf Ebrahimi 					FAIL_IF(push_inst(compiler, ADDI | RD(EQUAL_FLAG) | RS1(src1) | IMM_I(0)));
1455*22dc650dSSadaf Ebrahimi 					carry_src_r = EQUAL_FLAG;
1456*22dc650dSSadaf Ebrahimi 				}
1457*22dc650dSSadaf Ebrahimi 			}
1458*22dc650dSSadaf Ebrahimi 
1459*22dc650dSSadaf Ebrahimi 			FAIL_IF(push_inst(compiler, ADD | WORD | RD(dst) | RS1(src1) | RS2(src2)));
1460*22dc650dSSadaf Ebrahimi 		}
1461*22dc650dSSadaf Ebrahimi 
1462*22dc650dSSadaf Ebrahimi 		/* Carry is zero if a + b >= a or a + b >= b, otherwise it is 1. */
1463*22dc650dSSadaf Ebrahimi 		if (carry_src_r != 0) {
1464*22dc650dSSadaf Ebrahimi 			if (flags & SRC2_IMM)
1465*22dc650dSSadaf Ebrahimi 				FAIL_IF(push_inst(compiler, SLTUI | RD(EQUAL_FLAG) | RS1(dst) | IMM_I(src2)));
1466*22dc650dSSadaf Ebrahimi 			else
1467*22dc650dSSadaf Ebrahimi 				FAIL_IF(push_inst(compiler, SLTU | RD(EQUAL_FLAG) | RS1(dst) | RS2(carry_src_r)));
1468*22dc650dSSadaf Ebrahimi 		}
1469*22dc650dSSadaf Ebrahimi 
1470*22dc650dSSadaf Ebrahimi 		FAIL_IF(push_inst(compiler, ADD | WORD | RD(dst) | RS1(dst) | RS2(OTHER_FLAG)));
1471*22dc650dSSadaf Ebrahimi 
1472*22dc650dSSadaf Ebrahimi 		if (carry_src_r == 0)
1473*22dc650dSSadaf Ebrahimi 			return SLJIT_SUCCESS;
1474*22dc650dSSadaf Ebrahimi 
1475*22dc650dSSadaf Ebrahimi 		/* Set ULESS_FLAG (dst == 0) && (OTHER_FLAG == 1). */
1476*22dc650dSSadaf Ebrahimi 		FAIL_IF(push_inst(compiler, SLTU | RD(OTHER_FLAG) | RS1(dst) | RS2(OTHER_FLAG)));
1477*22dc650dSSadaf Ebrahimi 		/* Set carry flag. */
1478*22dc650dSSadaf Ebrahimi 		return push_inst(compiler, OR | RD(OTHER_FLAG) | RS1(OTHER_FLAG) | RS2(EQUAL_FLAG));
1479*22dc650dSSadaf Ebrahimi 
1480*22dc650dSSadaf Ebrahimi 	case SLJIT_SUB:
1481*22dc650dSSadaf Ebrahimi 		if ((flags & SRC2_IMM) && src2 == SIMM_MIN) {
1482*22dc650dSSadaf Ebrahimi 			FAIL_IF(push_inst(compiler, ADDI | RD(TMP_REG2) | RS1(TMP_ZERO) | IMM_I(src2)));
1483*22dc650dSSadaf Ebrahimi 			src2 = TMP_REG2;
1484*22dc650dSSadaf Ebrahimi 			flags &= ~SRC2_IMM;
1485*22dc650dSSadaf Ebrahimi 		}
1486*22dc650dSSadaf Ebrahimi 
1487*22dc650dSSadaf Ebrahimi 		is_handled = 0;
1488*22dc650dSSadaf Ebrahimi 
1489*22dc650dSSadaf Ebrahimi 		if (flags & SRC2_IMM) {
1490*22dc650dSSadaf Ebrahimi 			if (GET_FLAG_TYPE(op) == SLJIT_LESS) {
1491*22dc650dSSadaf Ebrahimi 				FAIL_IF(push_inst(compiler, SLTUI | RD(OTHER_FLAG) | RS1(src1) | IMM_I(src2)));
1492*22dc650dSSadaf Ebrahimi 				is_handled = 1;
1493*22dc650dSSadaf Ebrahimi 			}
1494*22dc650dSSadaf Ebrahimi 			else if (GET_FLAG_TYPE(op) == SLJIT_SIG_LESS) {
1495*22dc650dSSadaf Ebrahimi 				FAIL_IF(push_inst(compiler, SLTI | RD(OTHER_FLAG) | RS1(src1) | IMM_I(src2)));
1496*22dc650dSSadaf Ebrahimi 				is_handled = 1;
1497*22dc650dSSadaf Ebrahimi 			}
1498*22dc650dSSadaf Ebrahimi 		}
1499*22dc650dSSadaf Ebrahimi 
1500*22dc650dSSadaf Ebrahimi 		if (!is_handled && GET_FLAG_TYPE(op) >= SLJIT_LESS && GET_FLAG_TYPE(op) <= SLJIT_SIG_LESS_EQUAL) {
1501*22dc650dSSadaf Ebrahimi 			is_handled = 1;
1502*22dc650dSSadaf Ebrahimi 
1503*22dc650dSSadaf Ebrahimi 			if (flags & SRC2_IMM) {
1504*22dc650dSSadaf Ebrahimi 				reg = (src1 == TMP_REG1) ? TMP_REG2 : TMP_REG1;
1505*22dc650dSSadaf Ebrahimi 				FAIL_IF(push_inst(compiler, ADDI | RD(reg) | RS1(TMP_ZERO) | IMM_I(src2)));
1506*22dc650dSSadaf Ebrahimi 				src2 = reg;
1507*22dc650dSSadaf Ebrahimi 				flags &= ~SRC2_IMM;
1508*22dc650dSSadaf Ebrahimi 			}
1509*22dc650dSSadaf Ebrahimi 
1510*22dc650dSSadaf Ebrahimi 			switch (GET_FLAG_TYPE(op)) {
1511*22dc650dSSadaf Ebrahimi 			case SLJIT_LESS:
1512*22dc650dSSadaf Ebrahimi 				FAIL_IF(push_inst(compiler, SLTU | RD(OTHER_FLAG) | RS1(src1) | RS2(src2)));
1513*22dc650dSSadaf Ebrahimi 				break;
1514*22dc650dSSadaf Ebrahimi 			case SLJIT_GREATER:
1515*22dc650dSSadaf Ebrahimi 				FAIL_IF(push_inst(compiler, SLTU | RD(OTHER_FLAG) | RS1(src2) | RS2(src1)));
1516*22dc650dSSadaf Ebrahimi 				break;
1517*22dc650dSSadaf Ebrahimi 			case SLJIT_SIG_LESS:
1518*22dc650dSSadaf Ebrahimi 				FAIL_IF(push_inst(compiler, SLT | RD(OTHER_FLAG) | RS1(src1) | RS2(src2)));
1519*22dc650dSSadaf Ebrahimi 				break;
1520*22dc650dSSadaf Ebrahimi 			case SLJIT_SIG_GREATER:
1521*22dc650dSSadaf Ebrahimi 				FAIL_IF(push_inst(compiler, SLT | RD(OTHER_FLAG) | RS1(src2) | RS2(src1)));
1522*22dc650dSSadaf Ebrahimi 				break;
1523*22dc650dSSadaf Ebrahimi 			}
1524*22dc650dSSadaf Ebrahimi 		}
1525*22dc650dSSadaf Ebrahimi 
1526*22dc650dSSadaf Ebrahimi 		if (is_handled) {
1527*22dc650dSSadaf Ebrahimi 			if (flags & SRC2_IMM) {
1528*22dc650dSSadaf Ebrahimi 				if (op & SLJIT_SET_Z)
1529*22dc650dSSadaf Ebrahimi 					FAIL_IF(push_inst(compiler, ADDI | WORD | RD(EQUAL_FLAG) | RS1(src1) | IMM_I(-src2)));
1530*22dc650dSSadaf Ebrahimi 				if (!(flags & UNUSED_DEST))
1531*22dc650dSSadaf Ebrahimi 					return push_inst(compiler, ADDI | WORD | RD(dst) | RS1(src1) | IMM_I(-src2));
1532*22dc650dSSadaf Ebrahimi 			}
1533*22dc650dSSadaf Ebrahimi 			else {
1534*22dc650dSSadaf Ebrahimi 				if (op & SLJIT_SET_Z)
1535*22dc650dSSadaf Ebrahimi 					FAIL_IF(push_inst(compiler, SUB | WORD | RD(EQUAL_FLAG) | RS1(src1) | RS2(src2)));
1536*22dc650dSSadaf Ebrahimi 				if (!(flags & UNUSED_DEST))
1537*22dc650dSSadaf Ebrahimi 					return push_inst(compiler, SUB | WORD | RD(dst) | RS1(src1) | RS2(src2));
1538*22dc650dSSadaf Ebrahimi 			}
1539*22dc650dSSadaf Ebrahimi 			return SLJIT_SUCCESS;
1540*22dc650dSSadaf Ebrahimi 		}
1541*22dc650dSSadaf Ebrahimi 
1542*22dc650dSSadaf Ebrahimi 		is_overflow = GET_FLAG_TYPE(op) == SLJIT_OVERFLOW;
1543*22dc650dSSadaf Ebrahimi 		is_carry = GET_FLAG_TYPE(op) == SLJIT_CARRY;
1544*22dc650dSSadaf Ebrahimi 
1545*22dc650dSSadaf Ebrahimi 		if (flags & SRC2_IMM) {
1546*22dc650dSSadaf Ebrahimi 			if (is_overflow) {
1547*22dc650dSSadaf Ebrahimi 				if (src2 >= 0)
1548*22dc650dSSadaf Ebrahimi 					FAIL_IF(push_inst(compiler, ADDI | RD(EQUAL_FLAG) | RS1(src1) | IMM_I(0)));
1549*22dc650dSSadaf Ebrahimi 				else
1550*22dc650dSSadaf Ebrahimi 					FAIL_IF(push_inst(compiler, XORI | RD(EQUAL_FLAG) | RS1(src1) | IMM_I(-1)));
1551*22dc650dSSadaf Ebrahimi 			}
1552*22dc650dSSadaf Ebrahimi 			else if (op & SLJIT_SET_Z)
1553*22dc650dSSadaf Ebrahimi 				FAIL_IF(push_inst(compiler, ADDI | WORD | RD(EQUAL_FLAG) | RS1(src1) | IMM_I(-src2)));
1554*22dc650dSSadaf Ebrahimi 
1555*22dc650dSSadaf Ebrahimi 			if (is_overflow || is_carry)
1556*22dc650dSSadaf Ebrahimi 				FAIL_IF(push_inst(compiler, SLTUI | RD(OTHER_FLAG) | RS1(src1) | IMM_I(src2)));
1557*22dc650dSSadaf Ebrahimi 
1558*22dc650dSSadaf Ebrahimi 			/* Only the zero flag is needed. */
1559*22dc650dSSadaf Ebrahimi 			if (!(flags & UNUSED_DEST) || (op & VARIABLE_FLAG_MASK))
1560*22dc650dSSadaf Ebrahimi 				FAIL_IF(push_inst(compiler, ADDI | WORD | RD(dst) | RS1(src1) | IMM_I(-src2)));
1561*22dc650dSSadaf Ebrahimi 		}
1562*22dc650dSSadaf Ebrahimi 		else {
1563*22dc650dSSadaf Ebrahimi 			if (is_overflow)
1564*22dc650dSSadaf Ebrahimi 				FAIL_IF(push_inst(compiler, XOR | RD(EQUAL_FLAG) | RS1(src1) | RS2(src2)));
1565*22dc650dSSadaf Ebrahimi 			else if (op & SLJIT_SET_Z)
1566*22dc650dSSadaf Ebrahimi 				FAIL_IF(push_inst(compiler, SUB | WORD | RD(EQUAL_FLAG) | RS1(src1) | RS2(src2)));
1567*22dc650dSSadaf Ebrahimi 
1568*22dc650dSSadaf Ebrahimi 			if (is_overflow || is_carry)
1569*22dc650dSSadaf Ebrahimi 				FAIL_IF(push_inst(compiler, SLTU | RD(OTHER_FLAG) | RS1(src1) | RS2(src2)));
1570*22dc650dSSadaf Ebrahimi 
1571*22dc650dSSadaf Ebrahimi 			/* Only the zero flag is needed. */
1572*22dc650dSSadaf Ebrahimi 			if (!(flags & UNUSED_DEST) || (op & VARIABLE_FLAG_MASK))
1573*22dc650dSSadaf Ebrahimi 				FAIL_IF(push_inst(compiler, SUB | WORD | RD(dst) | RS1(src1) | RS2(src2)));
1574*22dc650dSSadaf Ebrahimi 		}
1575*22dc650dSSadaf Ebrahimi 
1576*22dc650dSSadaf Ebrahimi 		if (!is_overflow)
1577*22dc650dSSadaf Ebrahimi 			return SLJIT_SUCCESS;
1578*22dc650dSSadaf Ebrahimi 
1579*22dc650dSSadaf Ebrahimi 		FAIL_IF(push_inst(compiler, XOR | RD(TMP_REG1) | RS1(dst) | RS2(EQUAL_FLAG)));
1580*22dc650dSSadaf Ebrahimi 		if (op & SLJIT_SET_Z)
1581*22dc650dSSadaf Ebrahimi 			FAIL_IF(push_inst(compiler, ADDI | RD(EQUAL_FLAG) | RS1(dst) | IMM_I(0)));
1582*22dc650dSSadaf Ebrahimi 		FAIL_IF(push_inst(compiler, SRLI | WORD | RD(TMP_REG1) | RS1(TMP_REG1) | IMM_EXTEND(31)));
1583*22dc650dSSadaf Ebrahimi 		return push_inst(compiler, XOR | RD(OTHER_FLAG) | RS1(TMP_REG1) | RS2(OTHER_FLAG));
1584*22dc650dSSadaf Ebrahimi 
1585*22dc650dSSadaf Ebrahimi 	case SLJIT_SUBC:
1586*22dc650dSSadaf Ebrahimi 		if ((flags & SRC2_IMM) && src2 == SIMM_MIN) {
1587*22dc650dSSadaf Ebrahimi 			FAIL_IF(push_inst(compiler, ADDI | RD(TMP_REG2) | RS1(TMP_ZERO) | IMM_I(src2)));
1588*22dc650dSSadaf Ebrahimi 			src2 = TMP_REG2;
1589*22dc650dSSadaf Ebrahimi 			flags &= ~SRC2_IMM;
1590*22dc650dSSadaf Ebrahimi 		}
1591*22dc650dSSadaf Ebrahimi 
1592*22dc650dSSadaf Ebrahimi 		is_carry = GET_FLAG_TYPE(op) == SLJIT_CARRY;
1593*22dc650dSSadaf Ebrahimi 
1594*22dc650dSSadaf Ebrahimi 		if (flags & SRC2_IMM) {
1595*22dc650dSSadaf Ebrahimi 			if (is_carry)
1596*22dc650dSSadaf Ebrahimi 				FAIL_IF(push_inst(compiler, SLTUI | RD(EQUAL_FLAG) | RS1(src1) | IMM_I(src2)));
1597*22dc650dSSadaf Ebrahimi 
1598*22dc650dSSadaf Ebrahimi 			FAIL_IF(push_inst(compiler, ADDI | WORD | RD(dst) | RS1(src1) | IMM_I(-src2)));
1599*22dc650dSSadaf Ebrahimi 		}
1600*22dc650dSSadaf Ebrahimi 		else {
1601*22dc650dSSadaf Ebrahimi 			if (is_carry)
1602*22dc650dSSadaf Ebrahimi 				FAIL_IF(push_inst(compiler, SLTU | RD(EQUAL_FLAG) | RS1(src1) | RS2(src2)));
1603*22dc650dSSadaf Ebrahimi 
1604*22dc650dSSadaf Ebrahimi 			FAIL_IF(push_inst(compiler, SUB | WORD | RD(dst) | RS1(src1) | RS2(src2)));
1605*22dc650dSSadaf Ebrahimi 		}
1606*22dc650dSSadaf Ebrahimi 
1607*22dc650dSSadaf Ebrahimi 		if (is_carry)
1608*22dc650dSSadaf Ebrahimi 			FAIL_IF(push_inst(compiler, SLTU | RD(TMP_REG1) | RS1(dst) | RS2(OTHER_FLAG)));
1609*22dc650dSSadaf Ebrahimi 
1610*22dc650dSSadaf Ebrahimi 		FAIL_IF(push_inst(compiler, SUB | WORD | RD(dst) | RS1(dst) | RS2(OTHER_FLAG)));
1611*22dc650dSSadaf Ebrahimi 
1612*22dc650dSSadaf Ebrahimi 		if (!is_carry)
1613*22dc650dSSadaf Ebrahimi 			return SLJIT_SUCCESS;
1614*22dc650dSSadaf Ebrahimi 
1615*22dc650dSSadaf Ebrahimi 		return push_inst(compiler, OR | RD(OTHER_FLAG) | RS1(EQUAL_FLAG) | RS2(TMP_REG1));
1616*22dc650dSSadaf Ebrahimi 
1617*22dc650dSSadaf Ebrahimi 	case SLJIT_MUL:
1618*22dc650dSSadaf Ebrahimi 		SLJIT_ASSERT(!(flags & SRC2_IMM));
1619*22dc650dSSadaf Ebrahimi 
1620*22dc650dSSadaf Ebrahimi 		if (GET_FLAG_TYPE(op) != SLJIT_OVERFLOW)
1621*22dc650dSSadaf Ebrahimi 			return push_inst(compiler, MUL | WORD | RD(dst) | RS1(src1) | RS2(src2));
1622*22dc650dSSadaf Ebrahimi 
1623*22dc650dSSadaf Ebrahimi #if (defined SLJIT_CONFIG_RISCV_64 && SLJIT_CONFIG_RISCV_64)
1624*22dc650dSSadaf Ebrahimi 		if (word) {
1625*22dc650dSSadaf Ebrahimi 			FAIL_IF(push_inst(compiler, MUL | RD(OTHER_FLAG) | RS1(src1) | RS2(src2)));
1626*22dc650dSSadaf Ebrahimi 			FAIL_IF(push_inst(compiler, MUL | 0x8 | RD(dst) | RS1(src1) | RS2(src2)));
1627*22dc650dSSadaf Ebrahimi 			return push_inst(compiler, SUB | RD(OTHER_FLAG) | RS1(dst) | RS2(OTHER_FLAG));
1628*22dc650dSSadaf Ebrahimi 		}
1629*22dc650dSSadaf Ebrahimi #endif /* SLJIT_CONFIG_RISCV_64 */
1630*22dc650dSSadaf Ebrahimi 
1631*22dc650dSSadaf Ebrahimi 		FAIL_IF(push_inst(compiler, MULH | RD(EQUAL_FLAG) | RS1(src1) | RS2(src2)));
1632*22dc650dSSadaf Ebrahimi 		FAIL_IF(push_inst(compiler, MUL | RD(dst) | RS1(src1) | RS2(src2)));
1633*22dc650dSSadaf Ebrahimi #if (defined SLJIT_CONFIG_RISCV_32 && SLJIT_CONFIG_RISCV_32)
1634*22dc650dSSadaf Ebrahimi 		FAIL_IF(push_inst(compiler, SRAI | RD(OTHER_FLAG) | RS1(dst) | IMM_I(31)));
1635*22dc650dSSadaf Ebrahimi #else /* !SLJIT_CONFIG_RISCV_32 */
1636*22dc650dSSadaf Ebrahimi 		FAIL_IF(push_inst(compiler, SRAI | RD(OTHER_FLAG) | RS1(dst) | IMM_I(63)));
1637*22dc650dSSadaf Ebrahimi #endif /* SLJIT_CONFIG_RISCV_32 */
1638*22dc650dSSadaf Ebrahimi 		return push_inst(compiler, SUB | RD(OTHER_FLAG) | RS1(EQUAL_FLAG) | RS2(OTHER_FLAG));
1639*22dc650dSSadaf Ebrahimi 
1640*22dc650dSSadaf Ebrahimi 	case SLJIT_AND:
1641*22dc650dSSadaf Ebrahimi 		EMIT_LOGICAL(ANDI, AND);
1642*22dc650dSSadaf Ebrahimi 		return SLJIT_SUCCESS;
1643*22dc650dSSadaf Ebrahimi 
1644*22dc650dSSadaf Ebrahimi 	case SLJIT_OR:
1645*22dc650dSSadaf Ebrahimi 		EMIT_LOGICAL(ORI, OR);
1646*22dc650dSSadaf Ebrahimi 		return SLJIT_SUCCESS;
1647*22dc650dSSadaf Ebrahimi 
1648*22dc650dSSadaf Ebrahimi 	case SLJIT_XOR:
1649*22dc650dSSadaf Ebrahimi 		EMIT_LOGICAL(XORI, XOR);
1650*22dc650dSSadaf Ebrahimi 		return SLJIT_SUCCESS;
1651*22dc650dSSadaf Ebrahimi 
1652*22dc650dSSadaf Ebrahimi 	case SLJIT_SHL:
1653*22dc650dSSadaf Ebrahimi 	case SLJIT_MSHL:
1654*22dc650dSSadaf Ebrahimi 		EMIT_SHIFT(SLLI, SLL);
1655*22dc650dSSadaf Ebrahimi 		break;
1656*22dc650dSSadaf Ebrahimi 
1657*22dc650dSSadaf Ebrahimi 	case SLJIT_LSHR:
1658*22dc650dSSadaf Ebrahimi 	case SLJIT_MLSHR:
1659*22dc650dSSadaf Ebrahimi 		EMIT_SHIFT(SRLI, SRL);
1660*22dc650dSSadaf Ebrahimi 		break;
1661*22dc650dSSadaf Ebrahimi 
1662*22dc650dSSadaf Ebrahimi 	case SLJIT_ASHR:
1663*22dc650dSSadaf Ebrahimi 	case SLJIT_MASHR:
1664*22dc650dSSadaf Ebrahimi 		EMIT_SHIFT(SRAI, SRA);
1665*22dc650dSSadaf Ebrahimi 		break;
1666*22dc650dSSadaf Ebrahimi 
1667*22dc650dSSadaf Ebrahimi 	case SLJIT_ROTL:
1668*22dc650dSSadaf Ebrahimi 	case SLJIT_ROTR:
1669*22dc650dSSadaf Ebrahimi 		if (flags & SRC2_IMM) {
1670*22dc650dSSadaf Ebrahimi 			SLJIT_ASSERT(src2 != 0);
1671*22dc650dSSadaf Ebrahimi 
1672*22dc650dSSadaf Ebrahimi 			op_imm = (GET_OPCODE(op) == SLJIT_ROTL) ? SLLI : SRLI;
1673*22dc650dSSadaf Ebrahimi 			FAIL_IF(push_inst(compiler, op_imm | WORD | RD(OTHER_FLAG) | RS1(src1) | IMM_I(src2)));
1674*22dc650dSSadaf Ebrahimi 
1675*22dc650dSSadaf Ebrahimi #if (defined SLJIT_CONFIG_RISCV_64 && SLJIT_CONFIG_RISCV_64)
1676*22dc650dSSadaf Ebrahimi 			src2 = ((op & SLJIT_32) ? 32 : 64) - src2;
1677*22dc650dSSadaf Ebrahimi #else /* !SLJIT_CONFIG_RISCV_64 */
1678*22dc650dSSadaf Ebrahimi 			src2 = 32 - src2;
1679*22dc650dSSadaf Ebrahimi #endif /* SLJIT_CONFIG_RISCV_64 */
1680*22dc650dSSadaf Ebrahimi 			op_imm = (GET_OPCODE(op) == SLJIT_ROTL) ? SRLI : SLLI;
1681*22dc650dSSadaf Ebrahimi 			FAIL_IF(push_inst(compiler, op_imm | WORD | RD(dst) | RS1(src1) | IMM_I(src2)));
1682*22dc650dSSadaf Ebrahimi 			return push_inst(compiler, OR | RD(dst) | RS1(dst) | RS2(OTHER_FLAG));
1683*22dc650dSSadaf Ebrahimi 		}
1684*22dc650dSSadaf Ebrahimi 
1685*22dc650dSSadaf Ebrahimi 		if (src2 == TMP_ZERO) {
1686*22dc650dSSadaf Ebrahimi 			if (dst != src1)
1687*22dc650dSSadaf Ebrahimi 				return push_inst(compiler, ADDI | WORD | RD(dst) | RS1(src1) | IMM_I(0));
1688*22dc650dSSadaf Ebrahimi 			return SLJIT_SUCCESS;
1689*22dc650dSSadaf Ebrahimi 		}
1690*22dc650dSSadaf Ebrahimi 
1691*22dc650dSSadaf Ebrahimi 		FAIL_IF(push_inst(compiler, SUB | WORD | RD(EQUAL_FLAG) | RS1(TMP_ZERO) | RS2(src2)));
1692*22dc650dSSadaf Ebrahimi 		op_reg = (GET_OPCODE(op) == SLJIT_ROTL) ? SLL : SRL;
1693*22dc650dSSadaf Ebrahimi 		FAIL_IF(push_inst(compiler, op_reg | WORD | RD(OTHER_FLAG) | RS1(src1) | RS2(src2)));
1694*22dc650dSSadaf Ebrahimi 		op_reg = (GET_OPCODE(op) == SLJIT_ROTL) ? SRL : SLL;
1695*22dc650dSSadaf Ebrahimi 		FAIL_IF(push_inst(compiler, op_reg | WORD | RD(dst) | RS1(src1) | RS2(EQUAL_FLAG)));
1696*22dc650dSSadaf Ebrahimi 		return push_inst(compiler, OR | RD(dst) | RS1(dst) | RS2(OTHER_FLAG));
1697*22dc650dSSadaf Ebrahimi 
1698*22dc650dSSadaf Ebrahimi 	default:
1699*22dc650dSSadaf Ebrahimi 		SLJIT_UNREACHABLE();
1700*22dc650dSSadaf Ebrahimi 		return SLJIT_SUCCESS;
1701*22dc650dSSadaf Ebrahimi 	}
1702*22dc650dSSadaf Ebrahimi 
1703*22dc650dSSadaf Ebrahimi 	if (flags & SRC2_IMM) {
1704*22dc650dSSadaf Ebrahimi 		if (op & SLJIT_SET_Z)
1705*22dc650dSSadaf Ebrahimi 			FAIL_IF(push_inst(compiler, op_imm | WORD | RD(EQUAL_FLAG) | RS1(src1) | IMM_I(src2)));
1706*22dc650dSSadaf Ebrahimi 
1707*22dc650dSSadaf Ebrahimi 		if (flags & UNUSED_DEST)
1708*22dc650dSSadaf Ebrahimi 			return SLJIT_SUCCESS;
1709*22dc650dSSadaf Ebrahimi 		return push_inst(compiler, op_imm | WORD | RD(dst) | RS1(src1) | IMM_I(src2));
1710*22dc650dSSadaf Ebrahimi 	}
1711*22dc650dSSadaf Ebrahimi 
1712*22dc650dSSadaf Ebrahimi 	if (op & SLJIT_SET_Z)
1713*22dc650dSSadaf Ebrahimi 		FAIL_IF(push_inst(compiler, op_reg | WORD | RD(EQUAL_FLAG) | RS1(src1) | RS2(src2)));
1714*22dc650dSSadaf Ebrahimi 
1715*22dc650dSSadaf Ebrahimi 	if (flags & UNUSED_DEST)
1716*22dc650dSSadaf Ebrahimi 		return SLJIT_SUCCESS;
1717*22dc650dSSadaf Ebrahimi 	return push_inst(compiler, op_reg | WORD | RD(dst) | RS1(src1) | RS2(src2));
1718*22dc650dSSadaf Ebrahimi }
1719*22dc650dSSadaf Ebrahimi 
1720*22dc650dSSadaf Ebrahimi #undef IMM_EXTEND
1721*22dc650dSSadaf Ebrahimi 
emit_op(struct sljit_compiler * compiler,sljit_s32 op,sljit_s32 flags,sljit_s32 dst,sljit_sw dstw,sljit_s32 src1,sljit_sw src1w,sljit_s32 src2,sljit_sw src2w)1722*22dc650dSSadaf Ebrahimi static sljit_s32 emit_op(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 flags,
1723*22dc650dSSadaf Ebrahimi 	sljit_s32 dst, sljit_sw dstw,
1724*22dc650dSSadaf Ebrahimi 	sljit_s32 src1, sljit_sw src1w,
1725*22dc650dSSadaf Ebrahimi 	sljit_s32 src2, sljit_sw src2w)
1726*22dc650dSSadaf Ebrahimi {
1727*22dc650dSSadaf Ebrahimi 	/* arg1 goes to TMP_REG1 or src reg
1728*22dc650dSSadaf Ebrahimi 	   arg2 goes to TMP_REG2, imm or src reg
1729*22dc650dSSadaf Ebrahimi 	   TMP_REG3 can be used for caching
1730*22dc650dSSadaf Ebrahimi 	   result goes to TMP_REG2, so put result can use TMP_REG1 and TMP_REG3. */
1731*22dc650dSSadaf Ebrahimi 	sljit_s32 dst_r = TMP_REG2;
1732*22dc650dSSadaf Ebrahimi 	sljit_s32 src1_r;
1733*22dc650dSSadaf Ebrahimi 	sljit_sw src2_r = 0;
1734*22dc650dSSadaf Ebrahimi 	sljit_s32 src2_tmp_reg = (GET_OPCODE(op) >= SLJIT_OP2_BASE && FAST_IS_REG(src1)) ? TMP_REG1 : TMP_REG2;
1735*22dc650dSSadaf Ebrahimi 
1736*22dc650dSSadaf Ebrahimi 	if (!(flags & ALT_KEEP_CACHE)) {
1737*22dc650dSSadaf Ebrahimi 		compiler->cache_arg = 0;
1738*22dc650dSSadaf Ebrahimi 		compiler->cache_argw = 0;
1739*22dc650dSSadaf Ebrahimi 	}
1740*22dc650dSSadaf Ebrahimi 
1741*22dc650dSSadaf Ebrahimi 	if (dst == 0) {
1742*22dc650dSSadaf Ebrahimi 		SLJIT_ASSERT(HAS_FLAGS(op));
1743*22dc650dSSadaf Ebrahimi 		flags |= UNUSED_DEST;
1744*22dc650dSSadaf Ebrahimi 		dst = TMP_REG2;
1745*22dc650dSSadaf Ebrahimi 	}
1746*22dc650dSSadaf Ebrahimi 	else if (FAST_IS_REG(dst)) {
1747*22dc650dSSadaf Ebrahimi 		dst_r = dst;
1748*22dc650dSSadaf Ebrahimi 		flags |= REG_DEST;
1749*22dc650dSSadaf Ebrahimi 		if (flags & MOVE_OP)
1750*22dc650dSSadaf Ebrahimi 			src2_tmp_reg = dst_r;
1751*22dc650dSSadaf Ebrahimi 	}
1752*22dc650dSSadaf Ebrahimi 	else if ((dst & SLJIT_MEM) && !getput_arg_fast(compiler, flags | ARG_TEST, TMP_REG1, dst, dstw))
1753*22dc650dSSadaf Ebrahimi 		flags |= SLOW_DEST;
1754*22dc650dSSadaf Ebrahimi 
1755*22dc650dSSadaf Ebrahimi 	if (flags & IMM_OP) {
1756*22dc650dSSadaf Ebrahimi 		if (src2 == SLJIT_IMM && src2w != 0 && src2w <= SIMM_MAX && src2w >= SIMM_MIN) {
1757*22dc650dSSadaf Ebrahimi 			flags |= SRC2_IMM;
1758*22dc650dSSadaf Ebrahimi 			src2_r = src2w;
1759*22dc650dSSadaf Ebrahimi 		}
1760*22dc650dSSadaf Ebrahimi 		else if ((flags & CUMULATIVE_OP) && src1 == SLJIT_IMM && src1w != 0 && src1w <= SIMM_MAX && src1w >= SIMM_MIN) {
1761*22dc650dSSadaf Ebrahimi 			flags |= SRC2_IMM;
1762*22dc650dSSadaf Ebrahimi 			src2_r = src1w;
1763*22dc650dSSadaf Ebrahimi 
1764*22dc650dSSadaf Ebrahimi 			/* And swap arguments. */
1765*22dc650dSSadaf Ebrahimi 			src1 = src2;
1766*22dc650dSSadaf Ebrahimi 			src1w = src2w;
1767*22dc650dSSadaf Ebrahimi 			src2 = SLJIT_IMM;
1768*22dc650dSSadaf Ebrahimi 			/* src2w = src2_r unneeded. */
1769*22dc650dSSadaf Ebrahimi 		}
1770*22dc650dSSadaf Ebrahimi 	}
1771*22dc650dSSadaf Ebrahimi 
1772*22dc650dSSadaf Ebrahimi 	/* Source 1. */
1773*22dc650dSSadaf Ebrahimi 	if (FAST_IS_REG(src1)) {
1774*22dc650dSSadaf Ebrahimi 		src1_r = src1;
1775*22dc650dSSadaf Ebrahimi 		flags |= REG1_SOURCE;
1776*22dc650dSSadaf Ebrahimi 	} else if (src1 == SLJIT_IMM) {
1777*22dc650dSSadaf Ebrahimi 		if (src1w) {
1778*22dc650dSSadaf Ebrahimi 			FAIL_IF(load_immediate(compiler, TMP_REG1, src1w, TMP_REG3));
1779*22dc650dSSadaf Ebrahimi 			src1_r = TMP_REG1;
1780*22dc650dSSadaf Ebrahimi 		}
1781*22dc650dSSadaf Ebrahimi 		else
1782*22dc650dSSadaf Ebrahimi 			src1_r = TMP_ZERO;
1783*22dc650dSSadaf Ebrahimi 	} else {
1784*22dc650dSSadaf Ebrahimi 		if (getput_arg_fast(compiler, flags | LOAD_DATA, TMP_REG1, src1, src1w))
1785*22dc650dSSadaf Ebrahimi 			FAIL_IF(compiler->error);
1786*22dc650dSSadaf Ebrahimi 		else
1787*22dc650dSSadaf Ebrahimi 			flags |= SLOW_SRC1;
1788*22dc650dSSadaf Ebrahimi 		src1_r = TMP_REG1;
1789*22dc650dSSadaf Ebrahimi 	}
1790*22dc650dSSadaf Ebrahimi 
1791*22dc650dSSadaf Ebrahimi 	/* Source 2. */
1792*22dc650dSSadaf Ebrahimi 	if (FAST_IS_REG(src2)) {
1793*22dc650dSSadaf Ebrahimi 		src2_r = src2;
1794*22dc650dSSadaf Ebrahimi 		flags |= REG2_SOURCE;
1795*22dc650dSSadaf Ebrahimi 		if ((flags & (REG_DEST | MOVE_OP)) == MOVE_OP)
1796*22dc650dSSadaf Ebrahimi 			dst_r = (sljit_s32)src2_r;
1797*22dc650dSSadaf Ebrahimi 	} else if (src2 == SLJIT_IMM) {
1798*22dc650dSSadaf Ebrahimi 		if (!(flags & SRC2_IMM)) {
1799*22dc650dSSadaf Ebrahimi 			if (src2w) {
1800*22dc650dSSadaf Ebrahimi 				FAIL_IF(load_immediate(compiler, src2_tmp_reg, src2w, TMP_REG3));
1801*22dc650dSSadaf Ebrahimi 				src2_r = src2_tmp_reg;
1802*22dc650dSSadaf Ebrahimi 			} else {
1803*22dc650dSSadaf Ebrahimi 				src2_r = TMP_ZERO;
1804*22dc650dSSadaf Ebrahimi 				if (flags & MOVE_OP) {
1805*22dc650dSSadaf Ebrahimi 					if (dst & SLJIT_MEM)
1806*22dc650dSSadaf Ebrahimi 						dst_r = 0;
1807*22dc650dSSadaf Ebrahimi 					else
1808*22dc650dSSadaf Ebrahimi 						op = SLJIT_MOV;
1809*22dc650dSSadaf Ebrahimi 				}
1810*22dc650dSSadaf Ebrahimi 			}
1811*22dc650dSSadaf Ebrahimi 		}
1812*22dc650dSSadaf Ebrahimi 	} else {
1813*22dc650dSSadaf Ebrahimi 		if (getput_arg_fast(compiler, flags | LOAD_DATA, src2_tmp_reg, src2, src2w))
1814*22dc650dSSadaf Ebrahimi 			FAIL_IF(compiler->error);
1815*22dc650dSSadaf Ebrahimi 		else
1816*22dc650dSSadaf Ebrahimi 			flags |= SLOW_SRC2;
1817*22dc650dSSadaf Ebrahimi 		src2_r = src2_tmp_reg;
1818*22dc650dSSadaf Ebrahimi 	}
1819*22dc650dSSadaf Ebrahimi 
1820*22dc650dSSadaf Ebrahimi 	if ((flags & (SLOW_SRC1 | SLOW_SRC2)) == (SLOW_SRC1 | SLOW_SRC2)) {
1821*22dc650dSSadaf Ebrahimi 		SLJIT_ASSERT(src2_r == TMP_REG2);
1822*22dc650dSSadaf Ebrahimi 		if ((flags & SLOW_DEST) && !can_cache(src2, src2w, src1, src1w) && can_cache(src2, src2w, dst, dstw)) {
1823*22dc650dSSadaf Ebrahimi 			FAIL_IF(getput_arg(compiler, flags | LOAD_DATA, TMP_REG1, src1, src1w, src2, src2w));
1824*22dc650dSSadaf Ebrahimi 			FAIL_IF(getput_arg(compiler, flags | LOAD_DATA | MEM_USE_TMP2, TMP_REG2, src2, src2w, dst, dstw));
1825*22dc650dSSadaf Ebrahimi 		} else {
1826*22dc650dSSadaf Ebrahimi 			FAIL_IF(getput_arg(compiler, flags | LOAD_DATA, TMP_REG2, src2, src2w, src1, src1w));
1827*22dc650dSSadaf Ebrahimi 			FAIL_IF(getput_arg(compiler, flags | LOAD_DATA, TMP_REG1, src1, src1w, dst, dstw));
1828*22dc650dSSadaf Ebrahimi 		}
1829*22dc650dSSadaf Ebrahimi 	}
1830*22dc650dSSadaf Ebrahimi 	else if (flags & SLOW_SRC1)
1831*22dc650dSSadaf Ebrahimi 		FAIL_IF(getput_arg(compiler, flags | LOAD_DATA, TMP_REG1, src1, src1w, dst, dstw));
1832*22dc650dSSadaf Ebrahimi 	else if (flags & SLOW_SRC2)
1833*22dc650dSSadaf Ebrahimi 		FAIL_IF(getput_arg(compiler, flags | LOAD_DATA | ((src1_r == TMP_REG1) ? MEM_USE_TMP2 : 0), src2_tmp_reg, src2, src2w, dst, dstw));
1834*22dc650dSSadaf Ebrahimi 
1835*22dc650dSSadaf Ebrahimi 	FAIL_IF(emit_single_op(compiler, op, flags, dst_r, src1_r, src2_r));
1836*22dc650dSSadaf Ebrahimi 
1837*22dc650dSSadaf Ebrahimi 	if (dst & SLJIT_MEM) {
1838*22dc650dSSadaf Ebrahimi 		if (!(flags & SLOW_DEST)) {
1839*22dc650dSSadaf Ebrahimi 			getput_arg_fast(compiler, flags, dst_r, dst, dstw);
1840*22dc650dSSadaf Ebrahimi 			return compiler->error;
1841*22dc650dSSadaf Ebrahimi 		}
1842*22dc650dSSadaf Ebrahimi 		return getput_arg(compiler, flags, dst_r, dst, dstw, 0, 0);
1843*22dc650dSSadaf Ebrahimi 	}
1844*22dc650dSSadaf Ebrahimi 
1845*22dc650dSSadaf Ebrahimi 	return SLJIT_SUCCESS;
1846*22dc650dSSadaf Ebrahimi }
1847*22dc650dSSadaf Ebrahimi 
sljit_emit_op0(struct sljit_compiler * compiler,sljit_s32 op)1848*22dc650dSSadaf Ebrahimi SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op0(struct sljit_compiler *compiler, sljit_s32 op)
1849*22dc650dSSadaf Ebrahimi {
1850*22dc650dSSadaf Ebrahimi #if (defined SLJIT_CONFIG_RISCV_64 && SLJIT_CONFIG_RISCV_64)
1851*22dc650dSSadaf Ebrahimi 	sljit_ins word = (sljit_ins)(op & SLJIT_32) >> 5;
1852*22dc650dSSadaf Ebrahimi 
1853*22dc650dSSadaf Ebrahimi 	SLJIT_ASSERT(word == 0 || word == 0x8);
1854*22dc650dSSadaf Ebrahimi #endif /* SLJIT_CONFIG_RISCV_64 */
1855*22dc650dSSadaf Ebrahimi 
1856*22dc650dSSadaf Ebrahimi 	CHECK_ERROR();
1857*22dc650dSSadaf Ebrahimi 	CHECK(check_sljit_emit_op0(compiler, op));
1858*22dc650dSSadaf Ebrahimi 
1859*22dc650dSSadaf Ebrahimi 	switch (GET_OPCODE(op)) {
1860*22dc650dSSadaf Ebrahimi 	case SLJIT_BREAKPOINT:
1861*22dc650dSSadaf Ebrahimi 		return push_inst(compiler, EBREAK);
1862*22dc650dSSadaf Ebrahimi 	case SLJIT_NOP:
1863*22dc650dSSadaf Ebrahimi 		return push_inst(compiler, ADDI | RD(TMP_ZERO) | RS1(TMP_ZERO) | IMM_I(0));
1864*22dc650dSSadaf Ebrahimi 	case SLJIT_LMUL_UW:
1865*22dc650dSSadaf Ebrahimi 		FAIL_IF(push_inst(compiler, ADDI | RD(TMP_REG1) | RS1(SLJIT_R1) | IMM_I(0)));
1866*22dc650dSSadaf Ebrahimi 		FAIL_IF(push_inst(compiler, MULHU | RD(SLJIT_R1) | RS1(SLJIT_R0) | RS2(SLJIT_R1)));
1867*22dc650dSSadaf Ebrahimi 		return push_inst(compiler, MUL | RD(SLJIT_R0) | RS1(SLJIT_R0) | RS2(TMP_REG1));
1868*22dc650dSSadaf Ebrahimi 	case SLJIT_LMUL_SW:
1869*22dc650dSSadaf Ebrahimi 		FAIL_IF(push_inst(compiler, ADDI | RD(TMP_REG1) | RS1(SLJIT_R1) | IMM_I(0)));
1870*22dc650dSSadaf Ebrahimi 		FAIL_IF(push_inst(compiler, MULH | RD(SLJIT_R1) | RS1(SLJIT_R0) | RS2(SLJIT_R1)));
1871*22dc650dSSadaf Ebrahimi 		return push_inst(compiler, MUL | RD(SLJIT_R0) | RS1(SLJIT_R0) | RS2(TMP_REG1));
1872*22dc650dSSadaf Ebrahimi 	case SLJIT_DIVMOD_UW:
1873*22dc650dSSadaf Ebrahimi 		FAIL_IF(push_inst(compiler, ADDI | RD(TMP_REG1) | RS1(SLJIT_R0) | IMM_I(0)));
1874*22dc650dSSadaf Ebrahimi 		FAIL_IF(push_inst(compiler, DIVU | WORD | RD(SLJIT_R0) | RS1(SLJIT_R0) | RS2(SLJIT_R1)));
1875*22dc650dSSadaf Ebrahimi 		return push_inst(compiler, REMU | WORD | RD(SLJIT_R1) | RS1(TMP_REG1) | RS2(SLJIT_R1));
1876*22dc650dSSadaf Ebrahimi 	case SLJIT_DIVMOD_SW:
1877*22dc650dSSadaf Ebrahimi 		FAIL_IF(push_inst(compiler, ADDI | RD(TMP_REG1) | RS1(SLJIT_R0) | IMM_I(0)));
1878*22dc650dSSadaf Ebrahimi 		FAIL_IF(push_inst(compiler, DIV | WORD | RD(SLJIT_R0) | RS1(SLJIT_R0) | RS2(SLJIT_R1)));
1879*22dc650dSSadaf Ebrahimi 		return push_inst(compiler, REM | WORD | RD(SLJIT_R1) | RS1(TMP_REG1) | RS2(SLJIT_R1));
1880*22dc650dSSadaf Ebrahimi 	case SLJIT_DIV_UW:
1881*22dc650dSSadaf Ebrahimi 		return push_inst(compiler, DIVU | WORD | RD(SLJIT_R0) | RS1(SLJIT_R0) | RS2(SLJIT_R1));
1882*22dc650dSSadaf Ebrahimi 	case SLJIT_DIV_SW:
1883*22dc650dSSadaf Ebrahimi 		return push_inst(compiler, DIV | WORD | RD(SLJIT_R0) | RS1(SLJIT_R0) | RS2(SLJIT_R1));
1884*22dc650dSSadaf Ebrahimi 	case SLJIT_ENDBR:
1885*22dc650dSSadaf Ebrahimi 	case SLJIT_SKIP_FRAMES_BEFORE_RETURN:
1886*22dc650dSSadaf Ebrahimi 		return SLJIT_SUCCESS;
1887*22dc650dSSadaf Ebrahimi 	}
1888*22dc650dSSadaf Ebrahimi 
1889*22dc650dSSadaf Ebrahimi 	return SLJIT_SUCCESS;
1890*22dc650dSSadaf Ebrahimi }
1891*22dc650dSSadaf Ebrahimi 
sljit_emit_op1(struct sljit_compiler * compiler,sljit_s32 op,sljit_s32 dst,sljit_sw dstw,sljit_s32 src,sljit_sw srcw)1892*22dc650dSSadaf Ebrahimi SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op1(struct sljit_compiler *compiler, sljit_s32 op,
1893*22dc650dSSadaf Ebrahimi 	sljit_s32 dst, sljit_sw dstw,
1894*22dc650dSSadaf Ebrahimi 	sljit_s32 src, sljit_sw srcw)
1895*22dc650dSSadaf Ebrahimi {
1896*22dc650dSSadaf Ebrahimi 	sljit_s32 flags = 0;
1897*22dc650dSSadaf Ebrahimi 
1898*22dc650dSSadaf Ebrahimi 	CHECK_ERROR();
1899*22dc650dSSadaf Ebrahimi 	CHECK(check_sljit_emit_op1(compiler, op, dst, dstw, src, srcw));
1900*22dc650dSSadaf Ebrahimi 	ADJUST_LOCAL_OFFSET(dst, dstw);
1901*22dc650dSSadaf Ebrahimi 	ADJUST_LOCAL_OFFSET(src, srcw);
1902*22dc650dSSadaf Ebrahimi 
1903*22dc650dSSadaf Ebrahimi #if (defined SLJIT_CONFIG_RISCV_64 && SLJIT_CONFIG_RISCV_64)
1904*22dc650dSSadaf Ebrahimi 	if (op & SLJIT_32)
1905*22dc650dSSadaf Ebrahimi 		flags = INT_DATA | SIGNED_DATA;
1906*22dc650dSSadaf Ebrahimi #endif
1907*22dc650dSSadaf Ebrahimi 
1908*22dc650dSSadaf Ebrahimi 	switch (GET_OPCODE(op)) {
1909*22dc650dSSadaf Ebrahimi 	case SLJIT_MOV:
1910*22dc650dSSadaf Ebrahimi #if (defined SLJIT_CONFIG_RISCV_32 && SLJIT_CONFIG_RISCV_32)
1911*22dc650dSSadaf Ebrahimi 	case SLJIT_MOV_U32:
1912*22dc650dSSadaf Ebrahimi 	case SLJIT_MOV_S32:
1913*22dc650dSSadaf Ebrahimi 	case SLJIT_MOV32:
1914*22dc650dSSadaf Ebrahimi #endif
1915*22dc650dSSadaf Ebrahimi 	case SLJIT_MOV_P:
1916*22dc650dSSadaf Ebrahimi 		return emit_op(compiler, SLJIT_MOV, WORD_DATA | MOVE_OP, dst, dstw, TMP_ZERO, 0, src, srcw);
1917*22dc650dSSadaf Ebrahimi 
1918*22dc650dSSadaf Ebrahimi #if (defined SLJIT_CONFIG_RISCV_64 && SLJIT_CONFIG_RISCV_64)
1919*22dc650dSSadaf Ebrahimi 	case SLJIT_MOV_U32:
1920*22dc650dSSadaf Ebrahimi 		return emit_op(compiler, SLJIT_MOV_U32, INT_DATA | MOVE_OP, dst, dstw, TMP_ZERO, 0, src, (src == SLJIT_IMM) ? (sljit_u32)srcw : srcw);
1921*22dc650dSSadaf Ebrahimi 
1922*22dc650dSSadaf Ebrahimi 	case SLJIT_MOV_S32:
1923*22dc650dSSadaf Ebrahimi 	/* Logical operators have no W variant, so sign extended input is necessary for them. */
1924*22dc650dSSadaf Ebrahimi 	case SLJIT_MOV32:
1925*22dc650dSSadaf Ebrahimi 		return emit_op(compiler, SLJIT_MOV_S32, INT_DATA | SIGNED_DATA | MOVE_OP, dst, dstw, TMP_ZERO, 0, src, (src == SLJIT_IMM) ? (sljit_s32)srcw : srcw);
1926*22dc650dSSadaf Ebrahimi #endif
1927*22dc650dSSadaf Ebrahimi 
1928*22dc650dSSadaf Ebrahimi 	case SLJIT_MOV_U8:
1929*22dc650dSSadaf Ebrahimi 		return emit_op(compiler, op, BYTE_DATA | MOVE_OP, dst, dstw, TMP_ZERO, 0, src, (src == SLJIT_IMM) ? (sljit_u8)srcw : srcw);
1930*22dc650dSSadaf Ebrahimi 
1931*22dc650dSSadaf Ebrahimi 	case SLJIT_MOV_S8:
1932*22dc650dSSadaf Ebrahimi 		return emit_op(compiler, op, BYTE_DATA | SIGNED_DATA | MOVE_OP, dst, dstw, TMP_ZERO, 0, src, (src == SLJIT_IMM) ? (sljit_s8)srcw : srcw);
1933*22dc650dSSadaf Ebrahimi 
1934*22dc650dSSadaf Ebrahimi 	case SLJIT_MOV_U16:
1935*22dc650dSSadaf Ebrahimi 		return emit_op(compiler, op, HALF_DATA | MOVE_OP, dst, dstw, TMP_ZERO, 0, src, (src == SLJIT_IMM) ? (sljit_u16)srcw : srcw);
1936*22dc650dSSadaf Ebrahimi 
1937*22dc650dSSadaf Ebrahimi 	case SLJIT_MOV_S16:
1938*22dc650dSSadaf Ebrahimi 		return emit_op(compiler, op, HALF_DATA | SIGNED_DATA | MOVE_OP, dst, dstw, TMP_ZERO, 0, src, (src == SLJIT_IMM) ? (sljit_s16)srcw : srcw);
1939*22dc650dSSadaf Ebrahimi 
1940*22dc650dSSadaf Ebrahimi 	case SLJIT_CLZ:
1941*22dc650dSSadaf Ebrahimi 	case SLJIT_CTZ:
1942*22dc650dSSadaf Ebrahimi 	case SLJIT_REV:
1943*22dc650dSSadaf Ebrahimi 		return emit_op(compiler, op, flags, dst, dstw, TMP_ZERO, 0, src, srcw);
1944*22dc650dSSadaf Ebrahimi 
1945*22dc650dSSadaf Ebrahimi 	case SLJIT_REV_U16:
1946*22dc650dSSadaf Ebrahimi 	case SLJIT_REV_S16:
1947*22dc650dSSadaf Ebrahimi 		return emit_op(compiler, op, HALF_DATA, dst, dstw, TMP_ZERO, 0, src, srcw);
1948*22dc650dSSadaf Ebrahimi 
1949*22dc650dSSadaf Ebrahimi 	case SLJIT_REV_U32:
1950*22dc650dSSadaf Ebrahimi 	case SLJIT_REV_S32:
1951*22dc650dSSadaf Ebrahimi 		return emit_op(compiler, op | SLJIT_32, INT_DATA, dst, dstw, TMP_ZERO, 0, src, srcw);
1952*22dc650dSSadaf Ebrahimi 	}
1953*22dc650dSSadaf Ebrahimi 
1954*22dc650dSSadaf Ebrahimi 	SLJIT_UNREACHABLE();
1955*22dc650dSSadaf Ebrahimi 	return SLJIT_SUCCESS;
1956*22dc650dSSadaf Ebrahimi }
1957*22dc650dSSadaf Ebrahimi 
sljit_emit_op2(struct sljit_compiler * compiler,sljit_s32 op,sljit_s32 dst,sljit_sw dstw,sljit_s32 src1,sljit_sw src1w,sljit_s32 src2,sljit_sw src2w)1958*22dc650dSSadaf Ebrahimi SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op2(struct sljit_compiler *compiler, sljit_s32 op,
1959*22dc650dSSadaf Ebrahimi 	sljit_s32 dst, sljit_sw dstw,
1960*22dc650dSSadaf Ebrahimi 	sljit_s32 src1, sljit_sw src1w,
1961*22dc650dSSadaf Ebrahimi 	sljit_s32 src2, sljit_sw src2w)
1962*22dc650dSSadaf Ebrahimi {
1963*22dc650dSSadaf Ebrahimi 	sljit_s32 flags = 0;
1964*22dc650dSSadaf Ebrahimi 
1965*22dc650dSSadaf Ebrahimi 	CHECK_ERROR();
1966*22dc650dSSadaf Ebrahimi 	CHECK(check_sljit_emit_op2(compiler, op, 0, dst, dstw, src1, src1w, src2, src2w));
1967*22dc650dSSadaf Ebrahimi 	ADJUST_LOCAL_OFFSET(dst, dstw);
1968*22dc650dSSadaf Ebrahimi 	ADJUST_LOCAL_OFFSET(src1, src1w);
1969*22dc650dSSadaf Ebrahimi 	ADJUST_LOCAL_OFFSET(src2, src2w);
1970*22dc650dSSadaf Ebrahimi 
1971*22dc650dSSadaf Ebrahimi #if (defined SLJIT_CONFIG_RISCV_64 && SLJIT_CONFIG_RISCV_64)
1972*22dc650dSSadaf Ebrahimi 	if (op & SLJIT_32) {
1973*22dc650dSSadaf Ebrahimi 		flags |= INT_DATA | SIGNED_DATA;
1974*22dc650dSSadaf Ebrahimi 		if (src1 == SLJIT_IMM)
1975*22dc650dSSadaf Ebrahimi 			src1w = (sljit_s32)src1w;
1976*22dc650dSSadaf Ebrahimi 		if (src2 == SLJIT_IMM)
1977*22dc650dSSadaf Ebrahimi 			src2w = (sljit_s32)src2w;
1978*22dc650dSSadaf Ebrahimi 	}
1979*22dc650dSSadaf Ebrahimi #endif
1980*22dc650dSSadaf Ebrahimi 
1981*22dc650dSSadaf Ebrahimi 	switch (GET_OPCODE(op)) {
1982*22dc650dSSadaf Ebrahimi 	case SLJIT_ADD:
1983*22dc650dSSadaf Ebrahimi 	case SLJIT_ADDC:
1984*22dc650dSSadaf Ebrahimi 		compiler->status_flags_state = SLJIT_CURRENT_FLAGS_ADD;
1985*22dc650dSSadaf Ebrahimi 		return emit_op(compiler, op, flags | CUMULATIVE_OP | IMM_OP, dst, dstw, src1, src1w, src2, src2w);
1986*22dc650dSSadaf Ebrahimi 
1987*22dc650dSSadaf Ebrahimi 	case SLJIT_SUB:
1988*22dc650dSSadaf Ebrahimi 	case SLJIT_SUBC:
1989*22dc650dSSadaf Ebrahimi 		compiler->status_flags_state = SLJIT_CURRENT_FLAGS_SUB;
1990*22dc650dSSadaf Ebrahimi 		return emit_op(compiler, op, flags | IMM_OP, dst, dstw, src1, src1w, src2, src2w);
1991*22dc650dSSadaf Ebrahimi 
1992*22dc650dSSadaf Ebrahimi 	case SLJIT_MUL:
1993*22dc650dSSadaf Ebrahimi 		compiler->status_flags_state = 0;
1994*22dc650dSSadaf Ebrahimi 		return emit_op(compiler, op, flags | CUMULATIVE_OP, dst, dstw, src1, src1w, src2, src2w);
1995*22dc650dSSadaf Ebrahimi 
1996*22dc650dSSadaf Ebrahimi 	case SLJIT_AND:
1997*22dc650dSSadaf Ebrahimi 	case SLJIT_OR:
1998*22dc650dSSadaf Ebrahimi 	case SLJIT_XOR:
1999*22dc650dSSadaf Ebrahimi 		return emit_op(compiler, op, flags | CUMULATIVE_OP | IMM_OP, dst, dstw, src1, src1w, src2, src2w);
2000*22dc650dSSadaf Ebrahimi 
2001*22dc650dSSadaf Ebrahimi 	case SLJIT_SHL:
2002*22dc650dSSadaf Ebrahimi 	case SLJIT_MSHL:
2003*22dc650dSSadaf Ebrahimi 	case SLJIT_LSHR:
2004*22dc650dSSadaf Ebrahimi 	case SLJIT_MLSHR:
2005*22dc650dSSadaf Ebrahimi 	case SLJIT_ASHR:
2006*22dc650dSSadaf Ebrahimi 	case SLJIT_MASHR:
2007*22dc650dSSadaf Ebrahimi 	case SLJIT_ROTL:
2008*22dc650dSSadaf Ebrahimi 	case SLJIT_ROTR:
2009*22dc650dSSadaf Ebrahimi 		if (src2 == SLJIT_IMM) {
2010*22dc650dSSadaf Ebrahimi #if (defined SLJIT_CONFIG_RISCV_32 && SLJIT_CONFIG_RISCV_32)
2011*22dc650dSSadaf Ebrahimi 			src2w &= 0x1f;
2012*22dc650dSSadaf Ebrahimi #else /* !SLJIT_CONFIG_RISCV_32 */
2013*22dc650dSSadaf Ebrahimi 			if (op & SLJIT_32)
2014*22dc650dSSadaf Ebrahimi 				src2w &= 0x1f;
2015*22dc650dSSadaf Ebrahimi 			else
2016*22dc650dSSadaf Ebrahimi 				src2w &= 0x3f;
2017*22dc650dSSadaf Ebrahimi #endif /* SLJIT_CONFIG_RISCV_32 */
2018*22dc650dSSadaf Ebrahimi 		}
2019*22dc650dSSadaf Ebrahimi 
2020*22dc650dSSadaf Ebrahimi 		return emit_op(compiler, op, flags | IMM_OP, dst, dstw, src1, src1w, src2, src2w);
2021*22dc650dSSadaf Ebrahimi 	}
2022*22dc650dSSadaf Ebrahimi 
2023*22dc650dSSadaf Ebrahimi 	SLJIT_UNREACHABLE();
2024*22dc650dSSadaf Ebrahimi 	return SLJIT_SUCCESS;
2025*22dc650dSSadaf Ebrahimi }
2026*22dc650dSSadaf Ebrahimi 
sljit_emit_op2u(struct sljit_compiler * compiler,sljit_s32 op,sljit_s32 src1,sljit_sw src1w,sljit_s32 src2,sljit_sw src2w)2027*22dc650dSSadaf Ebrahimi SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op2u(struct sljit_compiler *compiler, sljit_s32 op,
2028*22dc650dSSadaf Ebrahimi 	sljit_s32 src1, sljit_sw src1w,
2029*22dc650dSSadaf Ebrahimi 	sljit_s32 src2, sljit_sw src2w)
2030*22dc650dSSadaf Ebrahimi {
2031*22dc650dSSadaf Ebrahimi 	CHECK_ERROR();
2032*22dc650dSSadaf Ebrahimi 	CHECK(check_sljit_emit_op2(compiler, op, 1, 0, 0, src1, src1w, src2, src2w));
2033*22dc650dSSadaf Ebrahimi 
2034*22dc650dSSadaf Ebrahimi 	SLJIT_SKIP_CHECKS(compiler);
2035*22dc650dSSadaf Ebrahimi 	return sljit_emit_op2(compiler, op, 0, 0, src1, src1w, src2, src2w);
2036*22dc650dSSadaf Ebrahimi }
2037*22dc650dSSadaf Ebrahimi 
sljit_emit_op2r(struct sljit_compiler * compiler,sljit_s32 op,sljit_s32 dst_reg,sljit_s32 src1,sljit_sw src1w,sljit_s32 src2,sljit_sw src2w)2038*22dc650dSSadaf Ebrahimi SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op2r(struct sljit_compiler *compiler, sljit_s32 op,
2039*22dc650dSSadaf Ebrahimi 	sljit_s32 dst_reg,
2040*22dc650dSSadaf Ebrahimi 	sljit_s32 src1, sljit_sw src1w,
2041*22dc650dSSadaf Ebrahimi 	sljit_s32 src2, sljit_sw src2w)
2042*22dc650dSSadaf Ebrahimi {
2043*22dc650dSSadaf Ebrahimi #if (defined SLJIT_CONFIG_RISCV_64 && SLJIT_CONFIG_RISCV_64)
2044*22dc650dSSadaf Ebrahimi 	sljit_ins word = (sljit_ins)(op & SLJIT_32) >> 5;
2045*22dc650dSSadaf Ebrahimi #endif /* SLJIT_CONFIG_RISCV_64 */
2046*22dc650dSSadaf Ebrahimi 
2047*22dc650dSSadaf Ebrahimi 	CHECK_ERROR();
2048*22dc650dSSadaf Ebrahimi 	CHECK(check_sljit_emit_op2r(compiler, op, dst_reg, src1, src1w, src2, src2w));
2049*22dc650dSSadaf Ebrahimi 
2050*22dc650dSSadaf Ebrahimi 	SLJIT_ASSERT(WORD == 0 || WORD == 0x8);
2051*22dc650dSSadaf Ebrahimi 
2052*22dc650dSSadaf Ebrahimi 	switch (GET_OPCODE(op)) {
2053*22dc650dSSadaf Ebrahimi 	case SLJIT_MULADD:
2054*22dc650dSSadaf Ebrahimi 		SLJIT_SKIP_CHECKS(compiler);
2055*22dc650dSSadaf Ebrahimi 		FAIL_IF(sljit_emit_op2(compiler, SLJIT_MUL | (op & SLJIT_32), TMP_REG2, 0, src1, src1w, src2, src2w));
2056*22dc650dSSadaf Ebrahimi 		return push_inst(compiler, ADD | WORD | RD(dst_reg) | RS1(dst_reg) | RS2(TMP_REG2));
2057*22dc650dSSadaf Ebrahimi 	}
2058*22dc650dSSadaf Ebrahimi 
2059*22dc650dSSadaf Ebrahimi 	return SLJIT_SUCCESS;
2060*22dc650dSSadaf Ebrahimi }
2061*22dc650dSSadaf Ebrahimi 
sljit_emit_shift_into(struct sljit_compiler * compiler,sljit_s32 op,sljit_s32 dst_reg,sljit_s32 src1_reg,sljit_s32 src2_reg,sljit_s32 src3,sljit_sw src3w)2062*22dc650dSSadaf Ebrahimi SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_shift_into(struct sljit_compiler *compiler, sljit_s32 op,
2063*22dc650dSSadaf Ebrahimi 	sljit_s32 dst_reg,
2064*22dc650dSSadaf Ebrahimi 	sljit_s32 src1_reg,
2065*22dc650dSSadaf Ebrahimi 	sljit_s32 src2_reg,
2066*22dc650dSSadaf Ebrahimi 	sljit_s32 src3, sljit_sw src3w)
2067*22dc650dSSadaf Ebrahimi {
2068*22dc650dSSadaf Ebrahimi 	sljit_s32 is_left;
2069*22dc650dSSadaf Ebrahimi 	sljit_ins ins1, ins2, ins3;
2070*22dc650dSSadaf Ebrahimi #if (defined SLJIT_CONFIG_RISCV_64 && SLJIT_CONFIG_RISCV_64)
2071*22dc650dSSadaf Ebrahimi 	sljit_ins word = (sljit_ins)(op & SLJIT_32) >> 5;
2072*22dc650dSSadaf Ebrahimi 	sljit_s32 inp_flags = ((op & SLJIT_32) ? INT_DATA : WORD_DATA) | LOAD_DATA;
2073*22dc650dSSadaf Ebrahimi 	sljit_sw bit_length = (op & SLJIT_32) ? 32 : 64;
2074*22dc650dSSadaf Ebrahimi #else /* !SLJIT_CONFIG_RISCV_64 */
2075*22dc650dSSadaf Ebrahimi 	sljit_s32 inp_flags = WORD_DATA | LOAD_DATA;
2076*22dc650dSSadaf Ebrahimi 	sljit_sw bit_length = 32;
2077*22dc650dSSadaf Ebrahimi #endif /* SLJIT_CONFIG_RISCV_64 */
2078*22dc650dSSadaf Ebrahimi 
2079*22dc650dSSadaf Ebrahimi 	SLJIT_ASSERT(WORD == 0 || WORD == 0x8);
2080*22dc650dSSadaf Ebrahimi 
2081*22dc650dSSadaf Ebrahimi 	CHECK_ERROR();
2082*22dc650dSSadaf Ebrahimi 	CHECK(check_sljit_emit_shift_into(compiler, op, dst_reg, src1_reg, src2_reg, src3, src3w));
2083*22dc650dSSadaf Ebrahimi 
2084*22dc650dSSadaf Ebrahimi 	is_left = (GET_OPCODE(op) == SLJIT_SHL || GET_OPCODE(op) == SLJIT_MSHL);
2085*22dc650dSSadaf Ebrahimi 
2086*22dc650dSSadaf Ebrahimi 	if (src1_reg == src2_reg) {
2087*22dc650dSSadaf Ebrahimi 		SLJIT_SKIP_CHECKS(compiler);
2088*22dc650dSSadaf Ebrahimi 		return sljit_emit_op2(compiler, (is_left ? SLJIT_ROTL : SLJIT_ROTR) | (op & SLJIT_32), dst_reg, 0, src1_reg, 0, src3, src3w);
2089*22dc650dSSadaf Ebrahimi 	}
2090*22dc650dSSadaf Ebrahimi 
2091*22dc650dSSadaf Ebrahimi 	ADJUST_LOCAL_OFFSET(src3, src3w);
2092*22dc650dSSadaf Ebrahimi 
2093*22dc650dSSadaf Ebrahimi 	if (src3 == SLJIT_IMM) {
2094*22dc650dSSadaf Ebrahimi 		src3w &= bit_length - 1;
2095*22dc650dSSadaf Ebrahimi 
2096*22dc650dSSadaf Ebrahimi 		if (src3w == 0)
2097*22dc650dSSadaf Ebrahimi 			return SLJIT_SUCCESS;
2098*22dc650dSSadaf Ebrahimi 
2099*22dc650dSSadaf Ebrahimi 		if (is_left) {
2100*22dc650dSSadaf Ebrahimi 			ins1 = SLLI | WORD | IMM_I(src3w);
2101*22dc650dSSadaf Ebrahimi 			src3w = bit_length - src3w;
2102*22dc650dSSadaf Ebrahimi 			ins2 = SRLI | WORD | IMM_I(src3w);
2103*22dc650dSSadaf Ebrahimi 		} else {
2104*22dc650dSSadaf Ebrahimi 			ins1 = SRLI | WORD | IMM_I(src3w);
2105*22dc650dSSadaf Ebrahimi 			src3w = bit_length - src3w;
2106*22dc650dSSadaf Ebrahimi 			ins2 = SLLI | WORD | IMM_I(src3w);
2107*22dc650dSSadaf Ebrahimi 		}
2108*22dc650dSSadaf Ebrahimi 
2109*22dc650dSSadaf Ebrahimi 		FAIL_IF(push_inst(compiler, ins1 | RD(dst_reg) | RS1(src1_reg)));
2110*22dc650dSSadaf Ebrahimi 		FAIL_IF(push_inst(compiler, ins2 | RD(TMP_REG1) | RS1(src2_reg)));
2111*22dc650dSSadaf Ebrahimi 		return push_inst(compiler, OR | RD(dst_reg) | RS1(dst_reg) | RS2(TMP_REG1));
2112*22dc650dSSadaf Ebrahimi 	}
2113*22dc650dSSadaf Ebrahimi 
2114*22dc650dSSadaf Ebrahimi 	if (src3 & SLJIT_MEM) {
2115*22dc650dSSadaf Ebrahimi 		FAIL_IF(emit_op_mem(compiler, inp_flags, TMP_REG2, src3, src3w));
2116*22dc650dSSadaf Ebrahimi 		src3 = TMP_REG2;
2117*22dc650dSSadaf Ebrahimi 	} else if (dst_reg == src3) {
2118*22dc650dSSadaf Ebrahimi 		push_inst(compiler, ADDI | WORD | RD(TMP_REG2) | RS1(src3) | IMM_I(0));
2119*22dc650dSSadaf Ebrahimi 		src3 = TMP_REG2;
2120*22dc650dSSadaf Ebrahimi 	}
2121*22dc650dSSadaf Ebrahimi 
2122*22dc650dSSadaf Ebrahimi 	if (is_left) {
2123*22dc650dSSadaf Ebrahimi 		ins1 = SLL;
2124*22dc650dSSadaf Ebrahimi 		ins2 = SRLI;
2125*22dc650dSSadaf Ebrahimi 		ins3 = SRL;
2126*22dc650dSSadaf Ebrahimi 	} else {
2127*22dc650dSSadaf Ebrahimi 		ins1 = SRL;
2128*22dc650dSSadaf Ebrahimi 		ins2 = SLLI;
2129*22dc650dSSadaf Ebrahimi 		ins3 = SLL;
2130*22dc650dSSadaf Ebrahimi 	}
2131*22dc650dSSadaf Ebrahimi 
2132*22dc650dSSadaf Ebrahimi 	FAIL_IF(push_inst(compiler, ins1 | WORD | RD(dst_reg) | RS1(src1_reg) | RS2(src3)));
2133*22dc650dSSadaf Ebrahimi 
2134*22dc650dSSadaf Ebrahimi 	if (!(op & SLJIT_SHIFT_INTO_NON_ZERO)) {
2135*22dc650dSSadaf Ebrahimi 		FAIL_IF(push_inst(compiler, ins2 | WORD | RD(TMP_REG1) | RS1(src2_reg) | IMM_I(1)));
2136*22dc650dSSadaf Ebrahimi 		FAIL_IF(push_inst(compiler, XORI | RD(TMP_REG2) | RS1(src3) | IMM_I((sljit_ins)bit_length - 1)));
2137*22dc650dSSadaf Ebrahimi 		src2_reg = TMP_REG1;
2138*22dc650dSSadaf Ebrahimi 	} else
2139*22dc650dSSadaf Ebrahimi 		FAIL_IF(push_inst(compiler, SUB | WORD | RD(TMP_REG2) | RS1(TMP_ZERO) | RS2(src3)));
2140*22dc650dSSadaf Ebrahimi 
2141*22dc650dSSadaf Ebrahimi 	FAIL_IF(push_inst(compiler, ins3 | WORD | RD(TMP_REG1) | RS1(src2_reg) | RS2(TMP_REG2)));
2142*22dc650dSSadaf Ebrahimi 	return push_inst(compiler, OR | RD(dst_reg) | RS1(dst_reg) | RS2(TMP_REG1));
2143*22dc650dSSadaf Ebrahimi }
2144*22dc650dSSadaf Ebrahimi 
sljit_emit_op_src(struct sljit_compiler * compiler,sljit_s32 op,sljit_s32 src,sljit_sw srcw)2145*22dc650dSSadaf Ebrahimi SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_src(struct sljit_compiler *compiler, sljit_s32 op,
2146*22dc650dSSadaf Ebrahimi 	sljit_s32 src, sljit_sw srcw)
2147*22dc650dSSadaf Ebrahimi {
2148*22dc650dSSadaf Ebrahimi 	CHECK_ERROR();
2149*22dc650dSSadaf Ebrahimi 	CHECK(check_sljit_emit_op_src(compiler, op, src, srcw));
2150*22dc650dSSadaf Ebrahimi 	ADJUST_LOCAL_OFFSET(src, srcw);
2151*22dc650dSSadaf Ebrahimi 
2152*22dc650dSSadaf Ebrahimi 	switch (op) {
2153*22dc650dSSadaf Ebrahimi 	case SLJIT_FAST_RETURN:
2154*22dc650dSSadaf Ebrahimi 		if (FAST_IS_REG(src))
2155*22dc650dSSadaf Ebrahimi 			FAIL_IF(push_inst(compiler, ADDI | RD(RETURN_ADDR_REG) | RS1(src) | IMM_I(0)));
2156*22dc650dSSadaf Ebrahimi 		else
2157*22dc650dSSadaf Ebrahimi 			FAIL_IF(emit_op_mem(compiler, WORD_DATA | LOAD_DATA, RETURN_ADDR_REG, src, srcw));
2158*22dc650dSSadaf Ebrahimi 
2159*22dc650dSSadaf Ebrahimi 		return push_inst(compiler, JALR | RD(TMP_ZERO) | RS1(RETURN_ADDR_REG) | IMM_I(0));
2160*22dc650dSSadaf Ebrahimi 	case SLJIT_SKIP_FRAMES_BEFORE_FAST_RETURN:
2161*22dc650dSSadaf Ebrahimi 		return SLJIT_SUCCESS;
2162*22dc650dSSadaf Ebrahimi 	case SLJIT_PREFETCH_L1:
2163*22dc650dSSadaf Ebrahimi 	case SLJIT_PREFETCH_L2:
2164*22dc650dSSadaf Ebrahimi 	case SLJIT_PREFETCH_L3:
2165*22dc650dSSadaf Ebrahimi 	case SLJIT_PREFETCH_ONCE:
2166*22dc650dSSadaf Ebrahimi 		return SLJIT_SUCCESS;
2167*22dc650dSSadaf Ebrahimi 	}
2168*22dc650dSSadaf Ebrahimi 
2169*22dc650dSSadaf Ebrahimi 	return SLJIT_SUCCESS;
2170*22dc650dSSadaf Ebrahimi }
2171*22dc650dSSadaf Ebrahimi 
sljit_emit_op_dst(struct sljit_compiler * compiler,sljit_s32 op,sljit_s32 dst,sljit_sw dstw)2172*22dc650dSSadaf Ebrahimi SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_dst(struct sljit_compiler *compiler, sljit_s32 op,
2173*22dc650dSSadaf Ebrahimi 	sljit_s32 dst, sljit_sw dstw)
2174*22dc650dSSadaf Ebrahimi {
2175*22dc650dSSadaf Ebrahimi 	sljit_s32 dst_r;
2176*22dc650dSSadaf Ebrahimi 
2177*22dc650dSSadaf Ebrahimi 	CHECK_ERROR();
2178*22dc650dSSadaf Ebrahimi 	CHECK(check_sljit_emit_op_dst(compiler, op, dst, dstw));
2179*22dc650dSSadaf Ebrahimi 	ADJUST_LOCAL_OFFSET(dst, dstw);
2180*22dc650dSSadaf Ebrahimi 
2181*22dc650dSSadaf Ebrahimi 	switch (op) {
2182*22dc650dSSadaf Ebrahimi 	case SLJIT_FAST_ENTER:
2183*22dc650dSSadaf Ebrahimi 		if (FAST_IS_REG(dst))
2184*22dc650dSSadaf Ebrahimi 			return push_inst(compiler, ADDI | RD(dst) | RS1(RETURN_ADDR_REG) | IMM_I(0));
2185*22dc650dSSadaf Ebrahimi 
2186*22dc650dSSadaf Ebrahimi 		SLJIT_ASSERT(RETURN_ADDR_REG == TMP_REG2);
2187*22dc650dSSadaf Ebrahimi 		break;
2188*22dc650dSSadaf Ebrahimi 	case SLJIT_GET_RETURN_ADDRESS:
2189*22dc650dSSadaf Ebrahimi 		dst_r = FAST_IS_REG(dst) ? dst : TMP_REG2;
2190*22dc650dSSadaf Ebrahimi 		FAIL_IF(emit_op_mem(compiler, WORD_DATA | LOAD_DATA, dst_r, SLJIT_MEM1(SLJIT_SP), compiler->local_size - SSIZE_OF(sw)));
2191*22dc650dSSadaf Ebrahimi 		break;
2192*22dc650dSSadaf Ebrahimi 	}
2193*22dc650dSSadaf Ebrahimi 
2194*22dc650dSSadaf Ebrahimi 	if (dst & SLJIT_MEM)
2195*22dc650dSSadaf Ebrahimi 		return emit_op_mem(compiler, WORD_DATA, TMP_REG2, dst, dstw);
2196*22dc650dSSadaf Ebrahimi 
2197*22dc650dSSadaf Ebrahimi 	return SLJIT_SUCCESS;
2198*22dc650dSSadaf Ebrahimi }
2199*22dc650dSSadaf Ebrahimi 
sljit_get_register_index(sljit_s32 type,sljit_s32 reg)2200*22dc650dSSadaf Ebrahimi SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_get_register_index(sljit_s32 type, sljit_s32 reg)
2201*22dc650dSSadaf Ebrahimi {
2202*22dc650dSSadaf Ebrahimi 	CHECK_REG_INDEX(check_sljit_get_register_index(type, reg));
2203*22dc650dSSadaf Ebrahimi 
2204*22dc650dSSadaf Ebrahimi 	if (type == SLJIT_GP_REGISTER)
2205*22dc650dSSadaf Ebrahimi 		return reg_map[reg];
2206*22dc650dSSadaf Ebrahimi 
2207*22dc650dSSadaf Ebrahimi 	if (type != SLJIT_FLOAT_REGISTER)
2208*22dc650dSSadaf Ebrahimi 		return -1;
2209*22dc650dSSadaf Ebrahimi 
2210*22dc650dSSadaf Ebrahimi 	return freg_map[reg];
2211*22dc650dSSadaf Ebrahimi }
2212*22dc650dSSadaf Ebrahimi 
sljit_emit_op_custom(struct sljit_compiler * compiler,void * instruction,sljit_u32 size)2213*22dc650dSSadaf Ebrahimi SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_custom(struct sljit_compiler *compiler,
2214*22dc650dSSadaf Ebrahimi 	void *instruction, sljit_u32 size)
2215*22dc650dSSadaf Ebrahimi {
2216*22dc650dSSadaf Ebrahimi 	SLJIT_UNUSED_ARG(size);
2217*22dc650dSSadaf Ebrahimi 
2218*22dc650dSSadaf Ebrahimi 	CHECK_ERROR();
2219*22dc650dSSadaf Ebrahimi 	CHECK(check_sljit_emit_op_custom(compiler, instruction, size));
2220*22dc650dSSadaf Ebrahimi 
2221*22dc650dSSadaf Ebrahimi 	return push_inst(compiler, *(sljit_ins*)instruction);
2222*22dc650dSSadaf Ebrahimi }
2223*22dc650dSSadaf Ebrahimi 
2224*22dc650dSSadaf Ebrahimi /* --------------------------------------------------------------------- */
2225*22dc650dSSadaf Ebrahimi /*  Floating point operators                                             */
2226*22dc650dSSadaf Ebrahimi /* --------------------------------------------------------------------- */
2227*22dc650dSSadaf Ebrahimi 
2228*22dc650dSSadaf Ebrahimi #define FLOAT_DATA(op) (DOUBLE_DATA | ((op & SLJIT_32) >> 7))
2229*22dc650dSSadaf Ebrahimi #define FMT(op) ((sljit_ins)((op & SLJIT_32) ^ SLJIT_32) << 17)
2230*22dc650dSSadaf Ebrahimi 
sljit_emit_fop1_conv_sw_from_f64(struct sljit_compiler * compiler,sljit_s32 op,sljit_s32 dst,sljit_sw dstw,sljit_s32 src,sljit_sw srcw)2231*22dc650dSSadaf Ebrahimi static SLJIT_INLINE sljit_s32 sljit_emit_fop1_conv_sw_from_f64(struct sljit_compiler *compiler, sljit_s32 op,
2232*22dc650dSSadaf Ebrahimi 	sljit_s32 dst, sljit_sw dstw,
2233*22dc650dSSadaf Ebrahimi 	sljit_s32 src, sljit_sw srcw)
2234*22dc650dSSadaf Ebrahimi {
2235*22dc650dSSadaf Ebrahimi #if (defined SLJIT_CONFIG_RISCV_32 && SLJIT_CONFIG_RISCV_32)
2236*22dc650dSSadaf Ebrahimi #	define flags (sljit_u32)0
2237*22dc650dSSadaf Ebrahimi #else
2238*22dc650dSSadaf Ebrahimi 	sljit_u32 flags = ((sljit_u32)(GET_OPCODE(op) == SLJIT_CONV_SW_FROM_F64)) << 21;
2239*22dc650dSSadaf Ebrahimi #endif
2240*22dc650dSSadaf Ebrahimi 	sljit_s32 dst_r = FAST_IS_REG(dst) ? dst : TMP_REG2;
2241*22dc650dSSadaf Ebrahimi 
2242*22dc650dSSadaf Ebrahimi 	if (src & SLJIT_MEM) {
2243*22dc650dSSadaf Ebrahimi 		FAIL_IF(emit_op_mem2(compiler, FLOAT_DATA(op) | LOAD_DATA, TMP_FREG1, src, srcw, dst, dstw));
2244*22dc650dSSadaf Ebrahimi 		src = TMP_FREG1;
2245*22dc650dSSadaf Ebrahimi 	}
2246*22dc650dSSadaf Ebrahimi 
2247*22dc650dSSadaf Ebrahimi 	FAIL_IF(push_inst(compiler, FCVT_W_S | FMT(op) | flags | RD(dst_r) | FRS1(src)));
2248*22dc650dSSadaf Ebrahimi 
2249*22dc650dSSadaf Ebrahimi 	/* Store the integer value from a VFP register. */
2250*22dc650dSSadaf Ebrahimi 	if (dst & SLJIT_MEM) {
2251*22dc650dSSadaf Ebrahimi #if (defined SLJIT_CONFIG_RISCV_32 && SLJIT_CONFIG_RISCV_32)
2252*22dc650dSSadaf Ebrahimi 		return emit_op_mem2(compiler, WORD_DATA, TMP_REG2, dst, dstw, 0, 0);
2253*22dc650dSSadaf Ebrahimi #else
2254*22dc650dSSadaf Ebrahimi 		return emit_op_mem2(compiler, flags ? WORD_DATA : INT_DATA, TMP_REG2, dst, dstw, 0, 0);
2255*22dc650dSSadaf Ebrahimi #endif
2256*22dc650dSSadaf Ebrahimi 	}
2257*22dc650dSSadaf Ebrahimi 	return SLJIT_SUCCESS;
2258*22dc650dSSadaf Ebrahimi 
2259*22dc650dSSadaf Ebrahimi #if (defined SLJIT_CONFIG_RISCV_32 && SLJIT_CONFIG_RISCV_32)
2260*22dc650dSSadaf Ebrahimi #	undef flags
2261*22dc650dSSadaf Ebrahimi #endif
2262*22dc650dSSadaf Ebrahimi }
2263*22dc650dSSadaf Ebrahimi 
sljit_emit_fop1_conv_f64_from_w(struct sljit_compiler * compiler,sljit_ins ins,sljit_s32 dst,sljit_sw dstw,sljit_s32 src,sljit_sw srcw)2264*22dc650dSSadaf Ebrahimi static sljit_s32 sljit_emit_fop1_conv_f64_from_w(struct sljit_compiler *compiler, sljit_ins ins,
2265*22dc650dSSadaf Ebrahimi 	sljit_s32 dst, sljit_sw dstw,
2266*22dc650dSSadaf Ebrahimi 	sljit_s32 src, sljit_sw srcw)
2267*22dc650dSSadaf Ebrahimi {
2268*22dc650dSSadaf Ebrahimi 	sljit_s32 dst_r = FAST_IS_REG(dst) ? dst : TMP_FREG1;
2269*22dc650dSSadaf Ebrahimi 
2270*22dc650dSSadaf Ebrahimi 	if (src & SLJIT_MEM) {
2271*22dc650dSSadaf Ebrahimi #if (defined SLJIT_CONFIG_RISCV_32 && SLJIT_CONFIG_RISCV_32)
2272*22dc650dSSadaf Ebrahimi 		FAIL_IF(emit_op_mem2(compiler, WORD_DATA | LOAD_DATA, TMP_REG1, src, srcw, dst, dstw));
2273*22dc650dSSadaf Ebrahimi #else /* SLJIT_CONFIG_RISCV_32 */
2274*22dc650dSSadaf Ebrahimi 		FAIL_IF(emit_op_mem2(compiler, ((ins & (1 << 21)) ? WORD_DATA : INT_DATA) | LOAD_DATA, TMP_REG1, src, srcw, dst, dstw));
2275*22dc650dSSadaf Ebrahimi #endif /* !SLJIT_CONFIG_RISCV_32 */
2276*22dc650dSSadaf Ebrahimi 		src = TMP_REG1;
2277*22dc650dSSadaf Ebrahimi 	} else if (src == SLJIT_IMM) {
2278*22dc650dSSadaf Ebrahimi 		FAIL_IF(load_immediate(compiler, TMP_REG1, srcw, TMP_REG3));
2279*22dc650dSSadaf Ebrahimi 		src = TMP_REG1;
2280*22dc650dSSadaf Ebrahimi 	}
2281*22dc650dSSadaf Ebrahimi 
2282*22dc650dSSadaf Ebrahimi 	FAIL_IF(push_inst(compiler, ins | FRD(dst_r) | RS1(src)));
2283*22dc650dSSadaf Ebrahimi 
2284*22dc650dSSadaf Ebrahimi 	if (dst & SLJIT_MEM)
2285*22dc650dSSadaf Ebrahimi 		return emit_op_mem2(compiler, DOUBLE_DATA | ((sljit_s32)(~ins >> 24) & 0x2), TMP_FREG1, dst, dstw, 0, 0);
2286*22dc650dSSadaf Ebrahimi 	return SLJIT_SUCCESS;
2287*22dc650dSSadaf Ebrahimi }
2288*22dc650dSSadaf Ebrahimi 
sljit_emit_fop1_conv_f64_from_sw(struct sljit_compiler * compiler,sljit_s32 op,sljit_s32 dst,sljit_sw dstw,sljit_s32 src,sljit_sw srcw)2289*22dc650dSSadaf Ebrahimi static SLJIT_INLINE sljit_s32 sljit_emit_fop1_conv_f64_from_sw(struct sljit_compiler *compiler, sljit_s32 op,
2290*22dc650dSSadaf Ebrahimi 	sljit_s32 dst, sljit_sw dstw,
2291*22dc650dSSadaf Ebrahimi 	sljit_s32 src, sljit_sw srcw)
2292*22dc650dSSadaf Ebrahimi {
2293*22dc650dSSadaf Ebrahimi 	sljit_ins ins = FCVT_S_W | FMT(op);
2294*22dc650dSSadaf Ebrahimi 
2295*22dc650dSSadaf Ebrahimi #if (defined SLJIT_CONFIG_RISCV_32 && SLJIT_CONFIG_RISCV_32)
2296*22dc650dSSadaf Ebrahimi 	if (op & SLJIT_32)
2297*22dc650dSSadaf Ebrahimi 		ins |= F3(0x7);
2298*22dc650dSSadaf Ebrahimi #else /* !SLJIT_CONFIG_RISCV_32 */
2299*22dc650dSSadaf Ebrahimi 	if (GET_OPCODE(op) == SLJIT_CONV_F64_FROM_SW)
2300*22dc650dSSadaf Ebrahimi 		ins |= (1 << 21);
2301*22dc650dSSadaf Ebrahimi 	else if (src == SLJIT_IMM)
2302*22dc650dSSadaf Ebrahimi 		srcw = (sljit_s32)srcw;
2303*22dc650dSSadaf Ebrahimi 
2304*22dc650dSSadaf Ebrahimi 	if (op != SLJIT_CONV_F64_FROM_S32)
2305*22dc650dSSadaf Ebrahimi 		ins |= F3(0x7);
2306*22dc650dSSadaf Ebrahimi #endif /* SLJIT_CONFIG_RISCV_32 */
2307*22dc650dSSadaf Ebrahimi 
2308*22dc650dSSadaf Ebrahimi 	return sljit_emit_fop1_conv_f64_from_w(compiler, ins, dst, dstw, src, srcw);
2309*22dc650dSSadaf Ebrahimi }
2310*22dc650dSSadaf Ebrahimi 
sljit_emit_fop1_conv_f64_from_uw(struct sljit_compiler * compiler,sljit_s32 op,sljit_s32 dst,sljit_sw dstw,sljit_s32 src,sljit_sw srcw)2311*22dc650dSSadaf Ebrahimi static SLJIT_INLINE sljit_s32 sljit_emit_fop1_conv_f64_from_uw(struct sljit_compiler *compiler, sljit_s32 op,
2312*22dc650dSSadaf Ebrahimi 	sljit_s32 dst, sljit_sw dstw,
2313*22dc650dSSadaf Ebrahimi 	sljit_s32 src, sljit_sw srcw)
2314*22dc650dSSadaf Ebrahimi {
2315*22dc650dSSadaf Ebrahimi 	sljit_ins ins = FCVT_S_WU | FMT(op);
2316*22dc650dSSadaf Ebrahimi 
2317*22dc650dSSadaf Ebrahimi #if (defined SLJIT_CONFIG_RISCV_32 && SLJIT_CONFIG_RISCV_32)
2318*22dc650dSSadaf Ebrahimi 	if (op & SLJIT_32)
2319*22dc650dSSadaf Ebrahimi 		ins |= F3(0x7);
2320*22dc650dSSadaf Ebrahimi #else /* !SLJIT_CONFIG_RISCV_32 */
2321*22dc650dSSadaf Ebrahimi 	if (GET_OPCODE(op) == SLJIT_CONV_F64_FROM_UW)
2322*22dc650dSSadaf Ebrahimi 		ins |= (1 << 21);
2323*22dc650dSSadaf Ebrahimi 	else if (src == SLJIT_IMM)
2324*22dc650dSSadaf Ebrahimi 		srcw = (sljit_u32)srcw;
2325*22dc650dSSadaf Ebrahimi 
2326*22dc650dSSadaf Ebrahimi 	if (op != SLJIT_CONV_F64_FROM_S32)
2327*22dc650dSSadaf Ebrahimi 		ins |= F3(0x7);
2328*22dc650dSSadaf Ebrahimi #endif /* SLJIT_CONFIG_RISCV_32 */
2329*22dc650dSSadaf Ebrahimi 
2330*22dc650dSSadaf Ebrahimi 	return sljit_emit_fop1_conv_f64_from_w(compiler, ins, dst, dstw, src, srcw);
2331*22dc650dSSadaf Ebrahimi }
2332*22dc650dSSadaf Ebrahimi 
sljit_emit_fop1_cmp(struct sljit_compiler * compiler,sljit_s32 op,sljit_s32 src1,sljit_sw src1w,sljit_s32 src2,sljit_sw src2w)2333*22dc650dSSadaf Ebrahimi static SLJIT_INLINE sljit_s32 sljit_emit_fop1_cmp(struct sljit_compiler *compiler, sljit_s32 op,
2334*22dc650dSSadaf Ebrahimi 	sljit_s32 src1, sljit_sw src1w,
2335*22dc650dSSadaf Ebrahimi 	sljit_s32 src2, sljit_sw src2w)
2336*22dc650dSSadaf Ebrahimi {
2337*22dc650dSSadaf Ebrahimi 	sljit_ins inst;
2338*22dc650dSSadaf Ebrahimi 
2339*22dc650dSSadaf Ebrahimi 	if (src1 & SLJIT_MEM) {
2340*22dc650dSSadaf Ebrahimi 		FAIL_IF(emit_op_mem2(compiler, FLOAT_DATA(op) | LOAD_DATA, TMP_FREG1, src1, src1w, src2, src2w));
2341*22dc650dSSadaf Ebrahimi 		src1 = TMP_FREG1;
2342*22dc650dSSadaf Ebrahimi 	}
2343*22dc650dSSadaf Ebrahimi 
2344*22dc650dSSadaf Ebrahimi 	if (src2 & SLJIT_MEM) {
2345*22dc650dSSadaf Ebrahimi 		FAIL_IF(emit_op_mem2(compiler, FLOAT_DATA(op) | LOAD_DATA, TMP_FREG2, src2, src2w, 0, 0));
2346*22dc650dSSadaf Ebrahimi 		src2 = TMP_FREG2;
2347*22dc650dSSadaf Ebrahimi 	}
2348*22dc650dSSadaf Ebrahimi 
2349*22dc650dSSadaf Ebrahimi 	switch (GET_FLAG_TYPE(op)) {
2350*22dc650dSSadaf Ebrahimi 	case SLJIT_F_EQUAL:
2351*22dc650dSSadaf Ebrahimi 	case SLJIT_ORDERED_EQUAL:
2352*22dc650dSSadaf Ebrahimi 		inst = FEQ_S | FMT(op) | RD(OTHER_FLAG) | FRS1(src1) | FRS2(src2);
2353*22dc650dSSadaf Ebrahimi 		break;
2354*22dc650dSSadaf Ebrahimi 	case SLJIT_F_LESS:
2355*22dc650dSSadaf Ebrahimi 	case SLJIT_ORDERED_LESS:
2356*22dc650dSSadaf Ebrahimi 		inst = FLT_S | FMT(op) | RD(OTHER_FLAG) | FRS1(src1) | FRS2(src2);
2357*22dc650dSSadaf Ebrahimi 		break;
2358*22dc650dSSadaf Ebrahimi 	case SLJIT_ORDERED_GREATER:
2359*22dc650dSSadaf Ebrahimi 		inst = FLT_S | FMT(op) | RD(OTHER_FLAG) | FRS1(src2) | FRS2(src1);
2360*22dc650dSSadaf Ebrahimi 		break;
2361*22dc650dSSadaf Ebrahimi 	case SLJIT_F_GREATER:
2362*22dc650dSSadaf Ebrahimi 	case SLJIT_UNORDERED_OR_GREATER:
2363*22dc650dSSadaf Ebrahimi 		inst = FLE_S | FMT(op) | RD(OTHER_FLAG) | FRS1(src1) | FRS2(src2);
2364*22dc650dSSadaf Ebrahimi 		break;
2365*22dc650dSSadaf Ebrahimi 	case SLJIT_UNORDERED_OR_LESS:
2366*22dc650dSSadaf Ebrahimi 		inst = FLE_S | FMT(op) | RD(OTHER_FLAG) | FRS1(src2) | FRS2(src1);
2367*22dc650dSSadaf Ebrahimi 		break;
2368*22dc650dSSadaf Ebrahimi 	case SLJIT_UNORDERED_OR_EQUAL:
2369*22dc650dSSadaf Ebrahimi 		FAIL_IF(push_inst(compiler, FLT_S | FMT(op) | RD(OTHER_FLAG) | FRS1(src1) | FRS2(src2)));
2370*22dc650dSSadaf Ebrahimi 		FAIL_IF(push_inst(compiler, FLT_S | FMT(op) | RD(TMP_REG1) | FRS1(src2) | FRS2(src1)));
2371*22dc650dSSadaf Ebrahimi 		inst = OR | RD(OTHER_FLAG) | RS1(OTHER_FLAG) | RS2(TMP_REG1);
2372*22dc650dSSadaf Ebrahimi 		break;
2373*22dc650dSSadaf Ebrahimi 	default: /* SLJIT_UNORDERED */
2374*22dc650dSSadaf Ebrahimi 		if (src1 == src2) {
2375*22dc650dSSadaf Ebrahimi 			inst = FEQ_S | FMT(op) | RD(OTHER_FLAG) | FRS1(src1) | FRS2(src1);
2376*22dc650dSSadaf Ebrahimi 			break;
2377*22dc650dSSadaf Ebrahimi 		}
2378*22dc650dSSadaf Ebrahimi 		FAIL_IF(push_inst(compiler, FEQ_S | FMT(op) | RD(OTHER_FLAG) | FRS1(src1) | FRS2(src1)));
2379*22dc650dSSadaf Ebrahimi 		FAIL_IF(push_inst(compiler, FEQ_S | FMT(op) | RD(TMP_REG1) | FRS1(src2) | FRS2(src2)));
2380*22dc650dSSadaf Ebrahimi 		inst = AND | RD(OTHER_FLAG) | RS1(OTHER_FLAG) | RS2(TMP_REG1);
2381*22dc650dSSadaf Ebrahimi 		break;
2382*22dc650dSSadaf Ebrahimi 	}
2383*22dc650dSSadaf Ebrahimi 
2384*22dc650dSSadaf Ebrahimi 	return push_inst(compiler, inst);
2385*22dc650dSSadaf Ebrahimi }
2386*22dc650dSSadaf Ebrahimi 
sljit_emit_fop1(struct sljit_compiler * compiler,sljit_s32 op,sljit_s32 dst,sljit_sw dstw,sljit_s32 src,sljit_sw srcw)2387*22dc650dSSadaf Ebrahimi SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fop1(struct sljit_compiler *compiler, sljit_s32 op,
2388*22dc650dSSadaf Ebrahimi 	sljit_s32 dst, sljit_sw dstw,
2389*22dc650dSSadaf Ebrahimi 	sljit_s32 src, sljit_sw srcw)
2390*22dc650dSSadaf Ebrahimi {
2391*22dc650dSSadaf Ebrahimi 	sljit_s32 dst_r;
2392*22dc650dSSadaf Ebrahimi 
2393*22dc650dSSadaf Ebrahimi 	CHECK_ERROR();
2394*22dc650dSSadaf Ebrahimi 	compiler->cache_arg = 0;
2395*22dc650dSSadaf Ebrahimi 	compiler->cache_argw = 0;
2396*22dc650dSSadaf Ebrahimi 
2397*22dc650dSSadaf Ebrahimi 	SLJIT_COMPILE_ASSERT((SLJIT_32 == 0x100) && !(DOUBLE_DATA & 0x2), float_transfer_bit_error);
2398*22dc650dSSadaf Ebrahimi 	SELECT_FOP1_OPERATION_WITH_CHECKS(compiler, op, dst, dstw, src, srcw);
2399*22dc650dSSadaf Ebrahimi 
2400*22dc650dSSadaf Ebrahimi 	if (GET_OPCODE(op) == SLJIT_CONV_F64_FROM_F32)
2401*22dc650dSSadaf Ebrahimi 		op ^= SLJIT_32;
2402*22dc650dSSadaf Ebrahimi 
2403*22dc650dSSadaf Ebrahimi 	dst_r = FAST_IS_REG(dst) ? dst : TMP_FREG1;
2404*22dc650dSSadaf Ebrahimi 
2405*22dc650dSSadaf Ebrahimi 	if (src & SLJIT_MEM) {
2406*22dc650dSSadaf Ebrahimi 		FAIL_IF(emit_op_mem2(compiler, FLOAT_DATA(op) | LOAD_DATA, dst_r, src, srcw, dst, dstw));
2407*22dc650dSSadaf Ebrahimi 		src = dst_r;
2408*22dc650dSSadaf Ebrahimi 	}
2409*22dc650dSSadaf Ebrahimi 
2410*22dc650dSSadaf Ebrahimi 	switch (GET_OPCODE(op)) {
2411*22dc650dSSadaf Ebrahimi 	case SLJIT_MOV_F64:
2412*22dc650dSSadaf Ebrahimi 		if (src != dst_r) {
2413*22dc650dSSadaf Ebrahimi 			if (!(dst & SLJIT_MEM))
2414*22dc650dSSadaf Ebrahimi 				FAIL_IF(push_inst(compiler, FSGNJ_S | FMT(op) | FRD(dst_r) | FRS1(src) | FRS2(src)));
2415*22dc650dSSadaf Ebrahimi 			else
2416*22dc650dSSadaf Ebrahimi 				dst_r = src;
2417*22dc650dSSadaf Ebrahimi 		}
2418*22dc650dSSadaf Ebrahimi 		break;
2419*22dc650dSSadaf Ebrahimi 	case SLJIT_NEG_F64:
2420*22dc650dSSadaf Ebrahimi 		FAIL_IF(push_inst(compiler, FSGNJN_S | FMT(op) | FRD(dst_r) | FRS1(src) | FRS2(src)));
2421*22dc650dSSadaf Ebrahimi 		break;
2422*22dc650dSSadaf Ebrahimi 	case SLJIT_ABS_F64:
2423*22dc650dSSadaf Ebrahimi 		FAIL_IF(push_inst(compiler, FSGNJX_S | FMT(op) | FRD(dst_r) | FRS1(src) | FRS2(src)));
2424*22dc650dSSadaf Ebrahimi 		break;
2425*22dc650dSSadaf Ebrahimi 	case SLJIT_CONV_F64_FROM_F32:
2426*22dc650dSSadaf Ebrahimi 		/* The SLJIT_32 bit is inverted because sljit_f32 needs to be loaded from the memory. */
2427*22dc650dSSadaf Ebrahimi 		FAIL_IF(push_inst(compiler, FCVT_S_D | ((op & SLJIT_32) ? (1 << 25) : ((1 << 20) | F3(7))) | FRD(dst_r) | FRS1(src)));
2428*22dc650dSSadaf Ebrahimi 		op ^= SLJIT_32;
2429*22dc650dSSadaf Ebrahimi 		break;
2430*22dc650dSSadaf Ebrahimi 	}
2431*22dc650dSSadaf Ebrahimi 
2432*22dc650dSSadaf Ebrahimi 	if (dst & SLJIT_MEM)
2433*22dc650dSSadaf Ebrahimi 		return emit_op_mem2(compiler, FLOAT_DATA(op), dst_r, dst, dstw, 0, 0);
2434*22dc650dSSadaf Ebrahimi 	return SLJIT_SUCCESS;
2435*22dc650dSSadaf Ebrahimi }
2436*22dc650dSSadaf Ebrahimi 
sljit_emit_fop2(struct sljit_compiler * compiler,sljit_s32 op,sljit_s32 dst,sljit_sw dstw,sljit_s32 src1,sljit_sw src1w,sljit_s32 src2,sljit_sw src2w)2437*22dc650dSSadaf Ebrahimi SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fop2(struct sljit_compiler *compiler, sljit_s32 op,
2438*22dc650dSSadaf Ebrahimi 	sljit_s32 dst, sljit_sw dstw,
2439*22dc650dSSadaf Ebrahimi 	sljit_s32 src1, sljit_sw src1w,
2440*22dc650dSSadaf Ebrahimi 	sljit_s32 src2, sljit_sw src2w)
2441*22dc650dSSadaf Ebrahimi {
2442*22dc650dSSadaf Ebrahimi 	sljit_s32 dst_r, flags = 0;
2443*22dc650dSSadaf Ebrahimi 
2444*22dc650dSSadaf Ebrahimi 	CHECK_ERROR();
2445*22dc650dSSadaf Ebrahimi 	CHECK(check_sljit_emit_fop2(compiler, op, dst, dstw, src1, src1w, src2, src2w));
2446*22dc650dSSadaf Ebrahimi 	ADJUST_LOCAL_OFFSET(dst, dstw);
2447*22dc650dSSadaf Ebrahimi 	ADJUST_LOCAL_OFFSET(src1, src1w);
2448*22dc650dSSadaf Ebrahimi 	ADJUST_LOCAL_OFFSET(src2, src2w);
2449*22dc650dSSadaf Ebrahimi 
2450*22dc650dSSadaf Ebrahimi 	compiler->cache_arg = 0;
2451*22dc650dSSadaf Ebrahimi 	compiler->cache_argw = 0;
2452*22dc650dSSadaf Ebrahimi 
2453*22dc650dSSadaf Ebrahimi 	dst_r = FAST_IS_REG(dst) ? dst : TMP_FREG2;
2454*22dc650dSSadaf Ebrahimi 
2455*22dc650dSSadaf Ebrahimi 	if (src1 & SLJIT_MEM) {
2456*22dc650dSSadaf Ebrahimi 		if (getput_arg_fast(compiler, FLOAT_DATA(op) | LOAD_DATA, TMP_FREG1, src1, src1w)) {
2457*22dc650dSSadaf Ebrahimi 			FAIL_IF(compiler->error);
2458*22dc650dSSadaf Ebrahimi 			src1 = TMP_FREG1;
2459*22dc650dSSadaf Ebrahimi 		} else
2460*22dc650dSSadaf Ebrahimi 			flags |= SLOW_SRC1;
2461*22dc650dSSadaf Ebrahimi 	}
2462*22dc650dSSadaf Ebrahimi 
2463*22dc650dSSadaf Ebrahimi 	if (src2 & SLJIT_MEM) {
2464*22dc650dSSadaf Ebrahimi 		if (getput_arg_fast(compiler, FLOAT_DATA(op) | LOAD_DATA, TMP_FREG2, src2, src2w)) {
2465*22dc650dSSadaf Ebrahimi 			FAIL_IF(compiler->error);
2466*22dc650dSSadaf Ebrahimi 			src2 = TMP_FREG2;
2467*22dc650dSSadaf Ebrahimi 		} else
2468*22dc650dSSadaf Ebrahimi 			flags |= SLOW_SRC2;
2469*22dc650dSSadaf Ebrahimi 	}
2470*22dc650dSSadaf Ebrahimi 
2471*22dc650dSSadaf Ebrahimi 	if ((flags & (SLOW_SRC1 | SLOW_SRC2)) == (SLOW_SRC1 | SLOW_SRC2)) {
2472*22dc650dSSadaf Ebrahimi 		if ((dst & SLJIT_MEM) && !can_cache(src1, src1w, src2, src2w) && can_cache(src1, src1w, dst, dstw)) {
2473*22dc650dSSadaf Ebrahimi 			FAIL_IF(getput_arg(compiler, FLOAT_DATA(op) | LOAD_DATA, TMP_FREG2, src2, src2w, src1, src1w));
2474*22dc650dSSadaf Ebrahimi 			FAIL_IF(getput_arg(compiler, FLOAT_DATA(op) | LOAD_DATA, TMP_FREG1, src1, src1w, dst, dstw));
2475*22dc650dSSadaf Ebrahimi 		} else {
2476*22dc650dSSadaf Ebrahimi 			FAIL_IF(getput_arg(compiler, FLOAT_DATA(op) | LOAD_DATA, TMP_FREG1, src1, src1w, src2, src2w));
2477*22dc650dSSadaf Ebrahimi 			FAIL_IF(getput_arg(compiler, FLOAT_DATA(op) | LOAD_DATA, TMP_FREG2, src2, src2w, dst, dstw));
2478*22dc650dSSadaf Ebrahimi 		}
2479*22dc650dSSadaf Ebrahimi 	}
2480*22dc650dSSadaf Ebrahimi 	else if (flags & SLOW_SRC1)
2481*22dc650dSSadaf Ebrahimi 		FAIL_IF(getput_arg(compiler, FLOAT_DATA(op) | LOAD_DATA, TMP_FREG1, src1, src1w, dst, dstw));
2482*22dc650dSSadaf Ebrahimi 	else if (flags & SLOW_SRC2)
2483*22dc650dSSadaf Ebrahimi 		FAIL_IF(getput_arg(compiler, FLOAT_DATA(op) | LOAD_DATA, TMP_FREG2, src2, src2w, dst, dstw));
2484*22dc650dSSadaf Ebrahimi 
2485*22dc650dSSadaf Ebrahimi 	if (flags & SLOW_SRC1)
2486*22dc650dSSadaf Ebrahimi 		src1 = TMP_FREG1;
2487*22dc650dSSadaf Ebrahimi 	if (flags & SLOW_SRC2)
2488*22dc650dSSadaf Ebrahimi 		src2 = TMP_FREG2;
2489*22dc650dSSadaf Ebrahimi 
2490*22dc650dSSadaf Ebrahimi 	switch (GET_OPCODE(op)) {
2491*22dc650dSSadaf Ebrahimi 	case SLJIT_ADD_F64:
2492*22dc650dSSadaf Ebrahimi 		FAIL_IF(push_inst(compiler, FADD_S | FMT(op) | FRD(dst_r) | FRS1(src1) | FRS2(src2)));
2493*22dc650dSSadaf Ebrahimi 		break;
2494*22dc650dSSadaf Ebrahimi 
2495*22dc650dSSadaf Ebrahimi 	case SLJIT_SUB_F64:
2496*22dc650dSSadaf Ebrahimi 		FAIL_IF(push_inst(compiler, FSUB_S | FMT(op) | FRD(dst_r) | FRS1(src1) | FRS2(src2)));
2497*22dc650dSSadaf Ebrahimi 		break;
2498*22dc650dSSadaf Ebrahimi 
2499*22dc650dSSadaf Ebrahimi 	case SLJIT_MUL_F64:
2500*22dc650dSSadaf Ebrahimi 		FAIL_IF(push_inst(compiler, FMUL_S | FMT(op) | FRD(dst_r) | FRS1(src1) | FRS2(src2)));
2501*22dc650dSSadaf Ebrahimi 		break;
2502*22dc650dSSadaf Ebrahimi 
2503*22dc650dSSadaf Ebrahimi 	case SLJIT_DIV_F64:
2504*22dc650dSSadaf Ebrahimi 		FAIL_IF(push_inst(compiler, FDIV_S | FMT(op) | FRD(dst_r) | FRS1(src1) | FRS2(src2)));
2505*22dc650dSSadaf Ebrahimi 		break;
2506*22dc650dSSadaf Ebrahimi 
2507*22dc650dSSadaf Ebrahimi 	case SLJIT_COPYSIGN_F64:
2508*22dc650dSSadaf Ebrahimi 		return push_inst(compiler, FSGNJ_S | FMT(op) | FRD(dst_r) | FRS1(src1) | FRS2(src2));
2509*22dc650dSSadaf Ebrahimi 	}
2510*22dc650dSSadaf Ebrahimi 
2511*22dc650dSSadaf Ebrahimi 	if (dst_r != dst)
2512*22dc650dSSadaf Ebrahimi 		FAIL_IF(emit_op_mem2(compiler, FLOAT_DATA(op), TMP_FREG2, dst, dstw, 0, 0));
2513*22dc650dSSadaf Ebrahimi 
2514*22dc650dSSadaf Ebrahimi 	return SLJIT_SUCCESS;
2515*22dc650dSSadaf Ebrahimi }
2516*22dc650dSSadaf Ebrahimi 
sljit_emit_fset32(struct sljit_compiler * compiler,sljit_s32 freg,sljit_f32 value)2517*22dc650dSSadaf Ebrahimi SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fset32(struct sljit_compiler *compiler,
2518*22dc650dSSadaf Ebrahimi 	sljit_s32 freg, sljit_f32 value)
2519*22dc650dSSadaf Ebrahimi {
2520*22dc650dSSadaf Ebrahimi 	union {
2521*22dc650dSSadaf Ebrahimi 		sljit_s32 imm;
2522*22dc650dSSadaf Ebrahimi 		sljit_f32 value;
2523*22dc650dSSadaf Ebrahimi 	} u;
2524*22dc650dSSadaf Ebrahimi 
2525*22dc650dSSadaf Ebrahimi 	CHECK_ERROR();
2526*22dc650dSSadaf Ebrahimi 	CHECK(check_sljit_emit_fset32(compiler, freg, value));
2527*22dc650dSSadaf Ebrahimi 
2528*22dc650dSSadaf Ebrahimi 	u.value = value;
2529*22dc650dSSadaf Ebrahimi 
2530*22dc650dSSadaf Ebrahimi 	if (u.imm == 0)
2531*22dc650dSSadaf Ebrahimi 		return push_inst(compiler, FMV_W_X | RS1(TMP_ZERO) | FRD(freg));
2532*22dc650dSSadaf Ebrahimi 
2533*22dc650dSSadaf Ebrahimi 	FAIL_IF(load_immediate(compiler, TMP_REG1, u.imm, TMP_REG3));
2534*22dc650dSSadaf Ebrahimi 	return push_inst(compiler, FMV_W_X | RS1(TMP_REG1) | FRD(freg));
2535*22dc650dSSadaf Ebrahimi }
2536*22dc650dSSadaf Ebrahimi 
2537*22dc650dSSadaf Ebrahimi /* --------------------------------------------------------------------- */
2538*22dc650dSSadaf Ebrahimi /*  Conditional instructions                                             */
2539*22dc650dSSadaf Ebrahimi /* --------------------------------------------------------------------- */
2540*22dc650dSSadaf Ebrahimi 
sljit_emit_label(struct sljit_compiler * compiler)2541*22dc650dSSadaf Ebrahimi SLJIT_API_FUNC_ATTRIBUTE struct sljit_label* sljit_emit_label(struct sljit_compiler *compiler)
2542*22dc650dSSadaf Ebrahimi {
2543*22dc650dSSadaf Ebrahimi 	struct sljit_label *label;
2544*22dc650dSSadaf Ebrahimi 
2545*22dc650dSSadaf Ebrahimi 	CHECK_ERROR_PTR();
2546*22dc650dSSadaf Ebrahimi 	CHECK_PTR(check_sljit_emit_label(compiler));
2547*22dc650dSSadaf Ebrahimi 
2548*22dc650dSSadaf Ebrahimi 	if (compiler->last_label && compiler->last_label->size == compiler->size)
2549*22dc650dSSadaf Ebrahimi 		return compiler->last_label;
2550*22dc650dSSadaf Ebrahimi 
2551*22dc650dSSadaf Ebrahimi 	label = (struct sljit_label*)ensure_abuf(compiler, sizeof(struct sljit_label));
2552*22dc650dSSadaf Ebrahimi 	PTR_FAIL_IF(!label);
2553*22dc650dSSadaf Ebrahimi 	set_label(label, compiler);
2554*22dc650dSSadaf Ebrahimi 	return label;
2555*22dc650dSSadaf Ebrahimi }
2556*22dc650dSSadaf Ebrahimi 
2557*22dc650dSSadaf Ebrahimi #if (defined SLJIT_CONFIG_RISCV_32 && SLJIT_CONFIG_RISCV_32)
2558*22dc650dSSadaf Ebrahimi #define BRANCH_LENGTH	((sljit_ins)(3 * sizeof(sljit_ins)) << 7)
2559*22dc650dSSadaf Ebrahimi #else
2560*22dc650dSSadaf Ebrahimi #define BRANCH_LENGTH	((sljit_ins)(7 * sizeof(sljit_ins)) << 7)
2561*22dc650dSSadaf Ebrahimi #endif
2562*22dc650dSSadaf Ebrahimi 
get_jump_instruction(sljit_s32 type)2563*22dc650dSSadaf Ebrahimi static sljit_ins get_jump_instruction(sljit_s32 type)
2564*22dc650dSSadaf Ebrahimi {
2565*22dc650dSSadaf Ebrahimi 	switch (type) {
2566*22dc650dSSadaf Ebrahimi 	case SLJIT_EQUAL:
2567*22dc650dSSadaf Ebrahimi 		return BNE | RS1(EQUAL_FLAG) | RS2(TMP_ZERO);
2568*22dc650dSSadaf Ebrahimi 	case SLJIT_NOT_EQUAL:
2569*22dc650dSSadaf Ebrahimi 		return BEQ | RS1(EQUAL_FLAG) | RS2(TMP_ZERO);
2570*22dc650dSSadaf Ebrahimi 	case SLJIT_LESS:
2571*22dc650dSSadaf Ebrahimi 	case SLJIT_GREATER:
2572*22dc650dSSadaf Ebrahimi 	case SLJIT_SIG_LESS:
2573*22dc650dSSadaf Ebrahimi 	case SLJIT_SIG_GREATER:
2574*22dc650dSSadaf Ebrahimi 	case SLJIT_OVERFLOW:
2575*22dc650dSSadaf Ebrahimi 	case SLJIT_CARRY:
2576*22dc650dSSadaf Ebrahimi 	case SLJIT_F_EQUAL:
2577*22dc650dSSadaf Ebrahimi 	case SLJIT_ORDERED_EQUAL:
2578*22dc650dSSadaf Ebrahimi 	case SLJIT_ORDERED_NOT_EQUAL:
2579*22dc650dSSadaf Ebrahimi 	case SLJIT_F_LESS:
2580*22dc650dSSadaf Ebrahimi 	case SLJIT_ORDERED_LESS:
2581*22dc650dSSadaf Ebrahimi 	case SLJIT_ORDERED_GREATER:
2582*22dc650dSSadaf Ebrahimi 	case SLJIT_F_LESS_EQUAL:
2583*22dc650dSSadaf Ebrahimi 	case SLJIT_ORDERED_LESS_EQUAL:
2584*22dc650dSSadaf Ebrahimi 	case SLJIT_ORDERED_GREATER_EQUAL:
2585*22dc650dSSadaf Ebrahimi 	case SLJIT_ORDERED:
2586*22dc650dSSadaf Ebrahimi 		return BEQ | RS1(OTHER_FLAG) | RS2(TMP_ZERO);
2587*22dc650dSSadaf Ebrahimi 		break;
2588*22dc650dSSadaf Ebrahimi 	case SLJIT_GREATER_EQUAL:
2589*22dc650dSSadaf Ebrahimi 	case SLJIT_LESS_EQUAL:
2590*22dc650dSSadaf Ebrahimi 	case SLJIT_SIG_GREATER_EQUAL:
2591*22dc650dSSadaf Ebrahimi 	case SLJIT_SIG_LESS_EQUAL:
2592*22dc650dSSadaf Ebrahimi 	case SLJIT_NOT_OVERFLOW:
2593*22dc650dSSadaf Ebrahimi 	case SLJIT_NOT_CARRY:
2594*22dc650dSSadaf Ebrahimi 	case SLJIT_F_NOT_EQUAL:
2595*22dc650dSSadaf Ebrahimi 	case SLJIT_UNORDERED_OR_NOT_EQUAL:
2596*22dc650dSSadaf Ebrahimi 	case SLJIT_UNORDERED_OR_EQUAL:
2597*22dc650dSSadaf Ebrahimi 	case SLJIT_F_GREATER_EQUAL:
2598*22dc650dSSadaf Ebrahimi 	case SLJIT_UNORDERED_OR_GREATER_EQUAL:
2599*22dc650dSSadaf Ebrahimi 	case SLJIT_UNORDERED_OR_LESS_EQUAL:
2600*22dc650dSSadaf Ebrahimi 	case SLJIT_F_GREATER:
2601*22dc650dSSadaf Ebrahimi 	case SLJIT_UNORDERED_OR_GREATER:
2602*22dc650dSSadaf Ebrahimi 	case SLJIT_UNORDERED_OR_LESS:
2603*22dc650dSSadaf Ebrahimi 	case SLJIT_UNORDERED:
2604*22dc650dSSadaf Ebrahimi 		return BNE | RS1(OTHER_FLAG) | RS2(TMP_ZERO);
2605*22dc650dSSadaf Ebrahimi 	default:
2606*22dc650dSSadaf Ebrahimi 		/* Not conditional branch. */
2607*22dc650dSSadaf Ebrahimi 		return 0;
2608*22dc650dSSadaf Ebrahimi 	}
2609*22dc650dSSadaf Ebrahimi }
2610*22dc650dSSadaf Ebrahimi 
sljit_emit_jump(struct sljit_compiler * compiler,sljit_s32 type)2611*22dc650dSSadaf Ebrahimi SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_jump(struct sljit_compiler *compiler, sljit_s32 type)
2612*22dc650dSSadaf Ebrahimi {
2613*22dc650dSSadaf Ebrahimi 	struct sljit_jump *jump;
2614*22dc650dSSadaf Ebrahimi 	sljit_ins inst;
2615*22dc650dSSadaf Ebrahimi 
2616*22dc650dSSadaf Ebrahimi 	CHECK_ERROR_PTR();
2617*22dc650dSSadaf Ebrahimi 	CHECK_PTR(check_sljit_emit_jump(compiler, type));
2618*22dc650dSSadaf Ebrahimi 
2619*22dc650dSSadaf Ebrahimi 	jump = (struct sljit_jump*)ensure_abuf(compiler, sizeof(struct sljit_jump));
2620*22dc650dSSadaf Ebrahimi 	PTR_FAIL_IF(!jump);
2621*22dc650dSSadaf Ebrahimi 	set_jump(jump, compiler, type & SLJIT_REWRITABLE_JUMP);
2622*22dc650dSSadaf Ebrahimi 	type &= 0xff;
2623*22dc650dSSadaf Ebrahimi 
2624*22dc650dSSadaf Ebrahimi 	inst = get_jump_instruction(type);
2625*22dc650dSSadaf Ebrahimi 
2626*22dc650dSSadaf Ebrahimi 	if (inst != 0) {
2627*22dc650dSSadaf Ebrahimi 		PTR_FAIL_IF(push_inst(compiler, inst | BRANCH_LENGTH));
2628*22dc650dSSadaf Ebrahimi 		jump->flags |= IS_COND;
2629*22dc650dSSadaf Ebrahimi 	}
2630*22dc650dSSadaf Ebrahimi 
2631*22dc650dSSadaf Ebrahimi 	jump->addr = compiler->size;
2632*22dc650dSSadaf Ebrahimi 	inst = JALR | RS1(TMP_REG1) | IMM_I(0);
2633*22dc650dSSadaf Ebrahimi 
2634*22dc650dSSadaf Ebrahimi 	if (type >= SLJIT_FAST_CALL) {
2635*22dc650dSSadaf Ebrahimi 		jump->flags |= IS_CALL;
2636*22dc650dSSadaf Ebrahimi 		inst |= RD(RETURN_ADDR_REG);
2637*22dc650dSSadaf Ebrahimi 	}
2638*22dc650dSSadaf Ebrahimi 
2639*22dc650dSSadaf Ebrahimi 	PTR_FAIL_IF(push_inst(compiler, inst));
2640*22dc650dSSadaf Ebrahimi 
2641*22dc650dSSadaf Ebrahimi 	/* Maximum number of instructions required for generating a constant. */
2642*22dc650dSSadaf Ebrahimi 	compiler->size += JUMP_MAX_SIZE - 1;
2643*22dc650dSSadaf Ebrahimi 	return jump;
2644*22dc650dSSadaf Ebrahimi }
2645*22dc650dSSadaf Ebrahimi 
sljit_emit_call(struct sljit_compiler * compiler,sljit_s32 type,sljit_s32 arg_types)2646*22dc650dSSadaf Ebrahimi SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_call(struct sljit_compiler *compiler, sljit_s32 type,
2647*22dc650dSSadaf Ebrahimi 	sljit_s32 arg_types)
2648*22dc650dSSadaf Ebrahimi {
2649*22dc650dSSadaf Ebrahimi 	SLJIT_UNUSED_ARG(arg_types);
2650*22dc650dSSadaf Ebrahimi 	CHECK_ERROR_PTR();
2651*22dc650dSSadaf Ebrahimi 	CHECK_PTR(check_sljit_emit_call(compiler, type, arg_types));
2652*22dc650dSSadaf Ebrahimi 
2653*22dc650dSSadaf Ebrahimi 	if (type & SLJIT_CALL_RETURN) {
2654*22dc650dSSadaf Ebrahimi 		PTR_FAIL_IF(emit_stack_frame_release(compiler, 0));
2655*22dc650dSSadaf Ebrahimi 		type = SLJIT_JUMP | (type & SLJIT_REWRITABLE_JUMP);
2656*22dc650dSSadaf Ebrahimi 	}
2657*22dc650dSSadaf Ebrahimi 
2658*22dc650dSSadaf Ebrahimi 	SLJIT_SKIP_CHECKS(compiler);
2659*22dc650dSSadaf Ebrahimi 	return sljit_emit_jump(compiler, type);
2660*22dc650dSSadaf Ebrahimi }
2661*22dc650dSSadaf Ebrahimi 
sljit_emit_cmp(struct sljit_compiler * compiler,sljit_s32 type,sljit_s32 src1,sljit_sw src1w,sljit_s32 src2,sljit_sw src2w)2662*22dc650dSSadaf Ebrahimi SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_cmp(struct sljit_compiler *compiler, sljit_s32 type,
2663*22dc650dSSadaf Ebrahimi 	sljit_s32 src1, sljit_sw src1w,
2664*22dc650dSSadaf Ebrahimi 	sljit_s32 src2, sljit_sw src2w)
2665*22dc650dSSadaf Ebrahimi {
2666*22dc650dSSadaf Ebrahimi 	struct sljit_jump *jump;
2667*22dc650dSSadaf Ebrahimi 	sljit_s32 flags;
2668*22dc650dSSadaf Ebrahimi 	sljit_ins inst;
2669*22dc650dSSadaf Ebrahimi 	sljit_s32 src2_tmp_reg = FAST_IS_REG(src1) ? TMP_REG1 : TMP_REG2;
2670*22dc650dSSadaf Ebrahimi 
2671*22dc650dSSadaf Ebrahimi 	CHECK_ERROR_PTR();
2672*22dc650dSSadaf Ebrahimi 	CHECK_PTR(check_sljit_emit_cmp(compiler, type, src1, src1w, src2, src2w));
2673*22dc650dSSadaf Ebrahimi 	ADJUST_LOCAL_OFFSET(src1, src1w);
2674*22dc650dSSadaf Ebrahimi 	ADJUST_LOCAL_OFFSET(src2, src2w);
2675*22dc650dSSadaf Ebrahimi 
2676*22dc650dSSadaf Ebrahimi 	compiler->cache_arg = 0;
2677*22dc650dSSadaf Ebrahimi 	compiler->cache_argw = 0;
2678*22dc650dSSadaf Ebrahimi #if (defined SLJIT_CONFIG_RISCV_32 && SLJIT_CONFIG_RISCV_32)
2679*22dc650dSSadaf Ebrahimi 	flags = WORD_DATA | LOAD_DATA;
2680*22dc650dSSadaf Ebrahimi #else /* !SLJIT_CONFIG_RISCV_32 */
2681*22dc650dSSadaf Ebrahimi 	flags = ((type & SLJIT_32) ? INT_DATA : WORD_DATA) | LOAD_DATA;
2682*22dc650dSSadaf Ebrahimi #endif /* SLJIT_CONFIG_RISCV_32 */
2683*22dc650dSSadaf Ebrahimi 
2684*22dc650dSSadaf Ebrahimi 	if (src1 & SLJIT_MEM) {
2685*22dc650dSSadaf Ebrahimi 		PTR_FAIL_IF(emit_op_mem2(compiler, flags, TMP_REG1, src1, src1w, src2, src2w));
2686*22dc650dSSadaf Ebrahimi 		src1 = TMP_REG1;
2687*22dc650dSSadaf Ebrahimi 	}
2688*22dc650dSSadaf Ebrahimi 
2689*22dc650dSSadaf Ebrahimi 	if (src2 & SLJIT_MEM) {
2690*22dc650dSSadaf Ebrahimi 		PTR_FAIL_IF(emit_op_mem2(compiler, flags, src2_tmp_reg, src2, src2w, 0, 0));
2691*22dc650dSSadaf Ebrahimi 		src2 = src2_tmp_reg;
2692*22dc650dSSadaf Ebrahimi 	}
2693*22dc650dSSadaf Ebrahimi 
2694*22dc650dSSadaf Ebrahimi 	if (src1 == SLJIT_IMM) {
2695*22dc650dSSadaf Ebrahimi 		if (src1w != 0) {
2696*22dc650dSSadaf Ebrahimi 			PTR_FAIL_IF(load_immediate(compiler, TMP_REG1, src1w, TMP_REG3));
2697*22dc650dSSadaf Ebrahimi 			src1 = TMP_REG1;
2698*22dc650dSSadaf Ebrahimi 		}
2699*22dc650dSSadaf Ebrahimi 		else
2700*22dc650dSSadaf Ebrahimi 			src1 = TMP_ZERO;
2701*22dc650dSSadaf Ebrahimi 	}
2702*22dc650dSSadaf Ebrahimi 
2703*22dc650dSSadaf Ebrahimi 	if (src2 == SLJIT_IMM) {
2704*22dc650dSSadaf Ebrahimi 		if (src2w != 0) {
2705*22dc650dSSadaf Ebrahimi 			PTR_FAIL_IF(load_immediate(compiler, src2_tmp_reg, src2w, TMP_REG3));
2706*22dc650dSSadaf Ebrahimi 			src2 = src2_tmp_reg;
2707*22dc650dSSadaf Ebrahimi 		}
2708*22dc650dSSadaf Ebrahimi 		else
2709*22dc650dSSadaf Ebrahimi 			src2 = TMP_ZERO;
2710*22dc650dSSadaf Ebrahimi 	}
2711*22dc650dSSadaf Ebrahimi 
2712*22dc650dSSadaf Ebrahimi 	jump = (struct sljit_jump*)ensure_abuf(compiler, sizeof(struct sljit_jump));
2713*22dc650dSSadaf Ebrahimi 	PTR_FAIL_IF(!jump);
2714*22dc650dSSadaf Ebrahimi 	set_jump(jump, compiler, (sljit_u32)((type & SLJIT_REWRITABLE_JUMP) | IS_COND));
2715*22dc650dSSadaf Ebrahimi 	type &= 0xff;
2716*22dc650dSSadaf Ebrahimi 
2717*22dc650dSSadaf Ebrahimi 	switch (type) {
2718*22dc650dSSadaf Ebrahimi 	case SLJIT_EQUAL:
2719*22dc650dSSadaf Ebrahimi 		inst = BNE | RS1(src1) | RS2(src2) | BRANCH_LENGTH;
2720*22dc650dSSadaf Ebrahimi 		break;
2721*22dc650dSSadaf Ebrahimi 	case SLJIT_NOT_EQUAL:
2722*22dc650dSSadaf Ebrahimi 		inst = BEQ | RS1(src1) | RS2(src2) | BRANCH_LENGTH;
2723*22dc650dSSadaf Ebrahimi 		break;
2724*22dc650dSSadaf Ebrahimi 	case SLJIT_LESS:
2725*22dc650dSSadaf Ebrahimi 		inst = BGEU | RS1(src1) | RS2(src2) | BRANCH_LENGTH;
2726*22dc650dSSadaf Ebrahimi 		break;
2727*22dc650dSSadaf Ebrahimi 	case SLJIT_GREATER_EQUAL:
2728*22dc650dSSadaf Ebrahimi 		inst = BLTU | RS1(src1) | RS2(src2) | BRANCH_LENGTH;
2729*22dc650dSSadaf Ebrahimi 		break;
2730*22dc650dSSadaf Ebrahimi 	case SLJIT_GREATER:
2731*22dc650dSSadaf Ebrahimi 		inst = BGEU | RS1(src2) | RS2(src1) | BRANCH_LENGTH;
2732*22dc650dSSadaf Ebrahimi 		break;
2733*22dc650dSSadaf Ebrahimi 	case SLJIT_LESS_EQUAL:
2734*22dc650dSSadaf Ebrahimi 		inst = BLTU | RS1(src2) | RS2(src1) | BRANCH_LENGTH;
2735*22dc650dSSadaf Ebrahimi 		break;
2736*22dc650dSSadaf Ebrahimi 	case SLJIT_SIG_LESS:
2737*22dc650dSSadaf Ebrahimi 		inst = BGE | RS1(src1) | RS2(src2) | BRANCH_LENGTH;
2738*22dc650dSSadaf Ebrahimi 		break;
2739*22dc650dSSadaf Ebrahimi 	case SLJIT_SIG_GREATER_EQUAL:
2740*22dc650dSSadaf Ebrahimi 		inst = BLT | RS1(src1) | RS2(src2) | BRANCH_LENGTH;
2741*22dc650dSSadaf Ebrahimi 		break;
2742*22dc650dSSadaf Ebrahimi 	case SLJIT_SIG_GREATER:
2743*22dc650dSSadaf Ebrahimi 		inst = BGE | RS1(src2) | RS2(src1) | BRANCH_LENGTH;
2744*22dc650dSSadaf Ebrahimi 		break;
2745*22dc650dSSadaf Ebrahimi 	case SLJIT_SIG_LESS_EQUAL:
2746*22dc650dSSadaf Ebrahimi 		inst = BLT | RS1(src2) | RS2(src1) | BRANCH_LENGTH;
2747*22dc650dSSadaf Ebrahimi 		break;
2748*22dc650dSSadaf Ebrahimi 	}
2749*22dc650dSSadaf Ebrahimi 
2750*22dc650dSSadaf Ebrahimi 	PTR_FAIL_IF(push_inst(compiler, inst));
2751*22dc650dSSadaf Ebrahimi 
2752*22dc650dSSadaf Ebrahimi 	jump->addr = compiler->size;
2753*22dc650dSSadaf Ebrahimi 	PTR_FAIL_IF(push_inst(compiler, JALR | RD(TMP_ZERO) | RS1(TMP_REG1) | IMM_I(0)));
2754*22dc650dSSadaf Ebrahimi 
2755*22dc650dSSadaf Ebrahimi 	/* Maximum number of instructions required for generating a constant. */
2756*22dc650dSSadaf Ebrahimi 	compiler->size += JUMP_MAX_SIZE - 1;
2757*22dc650dSSadaf Ebrahimi 	return jump;
2758*22dc650dSSadaf Ebrahimi }
2759*22dc650dSSadaf Ebrahimi 
2760*22dc650dSSadaf Ebrahimi #undef BRANCH_LENGTH
2761*22dc650dSSadaf Ebrahimi 
sljit_emit_ijump(struct sljit_compiler * compiler,sljit_s32 type,sljit_s32 src,sljit_sw srcw)2762*22dc650dSSadaf Ebrahimi SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_ijump(struct sljit_compiler *compiler, sljit_s32 type, sljit_s32 src, sljit_sw srcw)
2763*22dc650dSSadaf Ebrahimi {
2764*22dc650dSSadaf Ebrahimi 	struct sljit_jump *jump;
2765*22dc650dSSadaf Ebrahimi 
2766*22dc650dSSadaf Ebrahimi 	CHECK_ERROR();
2767*22dc650dSSadaf Ebrahimi 	CHECK(check_sljit_emit_ijump(compiler, type, src, srcw));
2768*22dc650dSSadaf Ebrahimi 
2769*22dc650dSSadaf Ebrahimi 	if (src != SLJIT_IMM) {
2770*22dc650dSSadaf Ebrahimi 		if (src & SLJIT_MEM) {
2771*22dc650dSSadaf Ebrahimi 			ADJUST_LOCAL_OFFSET(src, srcw);
2772*22dc650dSSadaf Ebrahimi 			FAIL_IF(emit_op_mem(compiler, WORD_DATA | LOAD_DATA, TMP_REG1, src, srcw));
2773*22dc650dSSadaf Ebrahimi 			src = TMP_REG1;
2774*22dc650dSSadaf Ebrahimi 		}
2775*22dc650dSSadaf Ebrahimi 		return push_inst(compiler, JALR | RD((type >= SLJIT_FAST_CALL) ? RETURN_ADDR_REG : TMP_ZERO) | RS1(src) | IMM_I(0));
2776*22dc650dSSadaf Ebrahimi 	}
2777*22dc650dSSadaf Ebrahimi 
2778*22dc650dSSadaf Ebrahimi 	/* These jumps are converted to jump/call instructions when possible. */
2779*22dc650dSSadaf Ebrahimi 	jump = (struct sljit_jump*)ensure_abuf(compiler, sizeof(struct sljit_jump));
2780*22dc650dSSadaf Ebrahimi 	FAIL_IF(!jump);
2781*22dc650dSSadaf Ebrahimi 	set_jump(jump, compiler, JUMP_ADDR | ((type >= SLJIT_FAST_CALL) ? IS_CALL : 0));
2782*22dc650dSSadaf Ebrahimi 	jump->u.target = (sljit_uw)srcw;
2783*22dc650dSSadaf Ebrahimi 
2784*22dc650dSSadaf Ebrahimi 	jump->addr = compiler->size;
2785*22dc650dSSadaf Ebrahimi 	FAIL_IF(push_inst(compiler, JALR | RD((type >= SLJIT_FAST_CALL) ? RETURN_ADDR_REG : TMP_ZERO) | RS1(TMP_REG1) | IMM_I(0)));
2786*22dc650dSSadaf Ebrahimi 
2787*22dc650dSSadaf Ebrahimi 	/* Maximum number of instructions required for generating a constant. */
2788*22dc650dSSadaf Ebrahimi 	compiler->size += JUMP_MAX_SIZE - 1;
2789*22dc650dSSadaf Ebrahimi 	return SLJIT_SUCCESS;
2790*22dc650dSSadaf Ebrahimi }
2791*22dc650dSSadaf Ebrahimi 
sljit_emit_icall(struct sljit_compiler * compiler,sljit_s32 type,sljit_s32 arg_types,sljit_s32 src,sljit_sw srcw)2792*22dc650dSSadaf Ebrahimi SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_icall(struct sljit_compiler *compiler, sljit_s32 type,
2793*22dc650dSSadaf Ebrahimi 	sljit_s32 arg_types,
2794*22dc650dSSadaf Ebrahimi 	sljit_s32 src, sljit_sw srcw)
2795*22dc650dSSadaf Ebrahimi {
2796*22dc650dSSadaf Ebrahimi 	SLJIT_UNUSED_ARG(arg_types);
2797*22dc650dSSadaf Ebrahimi 	CHECK_ERROR();
2798*22dc650dSSadaf Ebrahimi 	CHECK(check_sljit_emit_icall(compiler, type, arg_types, src, srcw));
2799*22dc650dSSadaf Ebrahimi 
2800*22dc650dSSadaf Ebrahimi 	if (src & SLJIT_MEM) {
2801*22dc650dSSadaf Ebrahimi 		ADJUST_LOCAL_OFFSET(src, srcw);
2802*22dc650dSSadaf Ebrahimi 		FAIL_IF(emit_op_mem(compiler, WORD_DATA | LOAD_DATA, TMP_REG1, src, srcw));
2803*22dc650dSSadaf Ebrahimi 		src = TMP_REG1;
2804*22dc650dSSadaf Ebrahimi 	}
2805*22dc650dSSadaf Ebrahimi 
2806*22dc650dSSadaf Ebrahimi 	if (type & SLJIT_CALL_RETURN) {
2807*22dc650dSSadaf Ebrahimi 		if (src >= SLJIT_FIRST_SAVED_REG && src <= (SLJIT_S0 - SLJIT_KEPT_SAVEDS_COUNT(compiler->options))) {
2808*22dc650dSSadaf Ebrahimi 			FAIL_IF(push_inst(compiler, ADDI | RD(TMP_REG1) | RS1(src) | IMM_I(0)));
2809*22dc650dSSadaf Ebrahimi 			src = TMP_REG1;
2810*22dc650dSSadaf Ebrahimi 		}
2811*22dc650dSSadaf Ebrahimi 
2812*22dc650dSSadaf Ebrahimi 		FAIL_IF(emit_stack_frame_release(compiler, 0));
2813*22dc650dSSadaf Ebrahimi 		type = SLJIT_JUMP;
2814*22dc650dSSadaf Ebrahimi 	}
2815*22dc650dSSadaf Ebrahimi 
2816*22dc650dSSadaf Ebrahimi 	SLJIT_SKIP_CHECKS(compiler);
2817*22dc650dSSadaf Ebrahimi 	return sljit_emit_ijump(compiler, type, src, srcw);
2818*22dc650dSSadaf Ebrahimi }
2819*22dc650dSSadaf Ebrahimi 
sljit_emit_op_flags(struct sljit_compiler * compiler,sljit_s32 op,sljit_s32 dst,sljit_sw dstw,sljit_s32 type)2820*22dc650dSSadaf Ebrahimi SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_flags(struct sljit_compiler *compiler, sljit_s32 op,
2821*22dc650dSSadaf Ebrahimi 	sljit_s32 dst, sljit_sw dstw,
2822*22dc650dSSadaf Ebrahimi 	sljit_s32 type)
2823*22dc650dSSadaf Ebrahimi {
2824*22dc650dSSadaf Ebrahimi 	sljit_s32 src_r, dst_r, invert;
2825*22dc650dSSadaf Ebrahimi 	sljit_s32 saved_op = op;
2826*22dc650dSSadaf Ebrahimi #if (defined SLJIT_CONFIG_RISCV_32 && SLJIT_CONFIG_RISCV_32)
2827*22dc650dSSadaf Ebrahimi 	sljit_s32 mem_type = WORD_DATA;
2828*22dc650dSSadaf Ebrahimi #else
2829*22dc650dSSadaf Ebrahimi 	sljit_s32 mem_type = ((op & SLJIT_32) || op == SLJIT_MOV32) ? (INT_DATA | SIGNED_DATA) : WORD_DATA;
2830*22dc650dSSadaf Ebrahimi #endif
2831*22dc650dSSadaf Ebrahimi 
2832*22dc650dSSadaf Ebrahimi 	CHECK_ERROR();
2833*22dc650dSSadaf Ebrahimi 	CHECK(check_sljit_emit_op_flags(compiler, op, dst, dstw, type));
2834*22dc650dSSadaf Ebrahimi 	ADJUST_LOCAL_OFFSET(dst, dstw);
2835*22dc650dSSadaf Ebrahimi 
2836*22dc650dSSadaf Ebrahimi 	op = GET_OPCODE(op);
2837*22dc650dSSadaf Ebrahimi 	dst_r = (op < SLJIT_ADD && FAST_IS_REG(dst)) ? dst : TMP_REG2;
2838*22dc650dSSadaf Ebrahimi 
2839*22dc650dSSadaf Ebrahimi 	compiler->cache_arg = 0;
2840*22dc650dSSadaf Ebrahimi 	compiler->cache_argw = 0;
2841*22dc650dSSadaf Ebrahimi 
2842*22dc650dSSadaf Ebrahimi 	if (op >= SLJIT_ADD && (dst & SLJIT_MEM))
2843*22dc650dSSadaf Ebrahimi 		FAIL_IF(emit_op_mem2(compiler, mem_type | LOAD_DATA, TMP_REG1, dst, dstw, dst, dstw));
2844*22dc650dSSadaf Ebrahimi 
2845*22dc650dSSadaf Ebrahimi 	if (type < SLJIT_F_EQUAL) {
2846*22dc650dSSadaf Ebrahimi 		src_r = OTHER_FLAG;
2847*22dc650dSSadaf Ebrahimi 		invert = type & 0x1;
2848*22dc650dSSadaf Ebrahimi 
2849*22dc650dSSadaf Ebrahimi 		switch (type) {
2850*22dc650dSSadaf Ebrahimi 		case SLJIT_EQUAL:
2851*22dc650dSSadaf Ebrahimi 		case SLJIT_NOT_EQUAL:
2852*22dc650dSSadaf Ebrahimi 			FAIL_IF(push_inst(compiler, SLTUI | RD(dst_r) | RS1(EQUAL_FLAG) | IMM_I(1)));
2853*22dc650dSSadaf Ebrahimi 			src_r = dst_r;
2854*22dc650dSSadaf Ebrahimi 			break;
2855*22dc650dSSadaf Ebrahimi 		case SLJIT_OVERFLOW:
2856*22dc650dSSadaf Ebrahimi 		case SLJIT_NOT_OVERFLOW:
2857*22dc650dSSadaf Ebrahimi 			if (compiler->status_flags_state & (SLJIT_CURRENT_FLAGS_ADD | SLJIT_CURRENT_FLAGS_SUB)) {
2858*22dc650dSSadaf Ebrahimi 				src_r = OTHER_FLAG;
2859*22dc650dSSadaf Ebrahimi 				break;
2860*22dc650dSSadaf Ebrahimi 			}
2861*22dc650dSSadaf Ebrahimi 			FAIL_IF(push_inst(compiler, SLTUI | RD(dst_r) | RS1(OTHER_FLAG) | IMM_I(1)));
2862*22dc650dSSadaf Ebrahimi 			src_r = dst_r;
2863*22dc650dSSadaf Ebrahimi 			invert ^= 0x1;
2864*22dc650dSSadaf Ebrahimi 			break;
2865*22dc650dSSadaf Ebrahimi 		}
2866*22dc650dSSadaf Ebrahimi 	} else {
2867*22dc650dSSadaf Ebrahimi 		invert = 0;
2868*22dc650dSSadaf Ebrahimi 		src_r = OTHER_FLAG;
2869*22dc650dSSadaf Ebrahimi 
2870*22dc650dSSadaf Ebrahimi 		switch (type) {
2871*22dc650dSSadaf Ebrahimi 		case SLJIT_F_NOT_EQUAL:
2872*22dc650dSSadaf Ebrahimi 		case SLJIT_UNORDERED_OR_NOT_EQUAL:
2873*22dc650dSSadaf Ebrahimi 		case SLJIT_UNORDERED_OR_EQUAL: /* Not supported. */
2874*22dc650dSSadaf Ebrahimi 		case SLJIT_F_GREATER_EQUAL:
2875*22dc650dSSadaf Ebrahimi 		case SLJIT_UNORDERED_OR_GREATER_EQUAL:
2876*22dc650dSSadaf Ebrahimi 		case SLJIT_UNORDERED_OR_LESS_EQUAL:
2877*22dc650dSSadaf Ebrahimi 		case SLJIT_F_GREATER:
2878*22dc650dSSadaf Ebrahimi 		case SLJIT_UNORDERED_OR_GREATER:
2879*22dc650dSSadaf Ebrahimi 		case SLJIT_UNORDERED_OR_LESS:
2880*22dc650dSSadaf Ebrahimi 		case SLJIT_UNORDERED:
2881*22dc650dSSadaf Ebrahimi 			invert = 1;
2882*22dc650dSSadaf Ebrahimi 			break;
2883*22dc650dSSadaf Ebrahimi 		}
2884*22dc650dSSadaf Ebrahimi 	}
2885*22dc650dSSadaf Ebrahimi 
2886*22dc650dSSadaf Ebrahimi 	if (invert) {
2887*22dc650dSSadaf Ebrahimi 		FAIL_IF(push_inst(compiler, XORI | RD(dst_r) | RS1(src_r) | IMM_I(1)));
2888*22dc650dSSadaf Ebrahimi 		src_r = dst_r;
2889*22dc650dSSadaf Ebrahimi 	}
2890*22dc650dSSadaf Ebrahimi 
2891*22dc650dSSadaf Ebrahimi 	if (op < SLJIT_ADD) {
2892*22dc650dSSadaf Ebrahimi 		if (dst & SLJIT_MEM)
2893*22dc650dSSadaf Ebrahimi 			return emit_op_mem(compiler, mem_type, src_r, dst, dstw);
2894*22dc650dSSadaf Ebrahimi 
2895*22dc650dSSadaf Ebrahimi 		if (src_r != dst_r)
2896*22dc650dSSadaf Ebrahimi 			return push_inst(compiler, ADDI | RD(dst_r) | RS1(src_r) | IMM_I(0));
2897*22dc650dSSadaf Ebrahimi 		return SLJIT_SUCCESS;
2898*22dc650dSSadaf Ebrahimi 	}
2899*22dc650dSSadaf Ebrahimi 
2900*22dc650dSSadaf Ebrahimi 	mem_type |= CUMULATIVE_OP | IMM_OP | ALT_KEEP_CACHE;
2901*22dc650dSSadaf Ebrahimi 
2902*22dc650dSSadaf Ebrahimi 	if (dst & SLJIT_MEM)
2903*22dc650dSSadaf Ebrahimi 		return emit_op(compiler, saved_op, mem_type, dst, dstw, TMP_REG1, 0, src_r, 0);
2904*22dc650dSSadaf Ebrahimi 	return emit_op(compiler, saved_op, mem_type, dst, dstw, dst, dstw, src_r, 0);
2905*22dc650dSSadaf Ebrahimi }
2906*22dc650dSSadaf Ebrahimi 
sljit_emit_select(struct sljit_compiler * compiler,sljit_s32 type,sljit_s32 dst_reg,sljit_s32 src1,sljit_sw src1w,sljit_s32 src2_reg)2907*22dc650dSSadaf Ebrahimi SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_select(struct sljit_compiler *compiler, sljit_s32 type,
2908*22dc650dSSadaf Ebrahimi 	sljit_s32 dst_reg,
2909*22dc650dSSadaf Ebrahimi 	sljit_s32 src1, sljit_sw src1w,
2910*22dc650dSSadaf Ebrahimi 	sljit_s32 src2_reg)
2911*22dc650dSSadaf Ebrahimi {
2912*22dc650dSSadaf Ebrahimi 	sljit_ins *ptr;
2913*22dc650dSSadaf Ebrahimi 	sljit_uw size;
2914*22dc650dSSadaf Ebrahimi #if (defined SLJIT_CONFIG_RISCV_64 && SLJIT_CONFIG_RISCV_64)
2915*22dc650dSSadaf Ebrahimi 	sljit_ins word = (sljit_ins)(type & SLJIT_32) >> 5;
2916*22dc650dSSadaf Ebrahimi 	sljit_s32 inp_flags = ((type & SLJIT_32) ? INT_DATA : WORD_DATA) | LOAD_DATA;
2917*22dc650dSSadaf Ebrahimi #else /* !SLJIT_CONFIG_RISCV_64 */
2918*22dc650dSSadaf Ebrahimi         sljit_s32 inp_flags = WORD_DATA | LOAD_DATA;
2919*22dc650dSSadaf Ebrahimi #endif /* SLJIT_CONFIG_RISCV_64 */
2920*22dc650dSSadaf Ebrahimi 
2921*22dc650dSSadaf Ebrahimi 	SLJIT_ASSERT(WORD == 0 || WORD == 0x8);
2922*22dc650dSSadaf Ebrahimi 
2923*22dc650dSSadaf Ebrahimi 	CHECK_ERROR();
2924*22dc650dSSadaf Ebrahimi 	CHECK(check_sljit_emit_select(compiler, type, dst_reg, src1, src1w, src2_reg));
2925*22dc650dSSadaf Ebrahimi 
2926*22dc650dSSadaf Ebrahimi 	ADJUST_LOCAL_OFFSET(src1, src1w);
2927*22dc650dSSadaf Ebrahimi 
2928*22dc650dSSadaf Ebrahimi 	if (dst_reg != src2_reg) {
2929*22dc650dSSadaf Ebrahimi 		if (dst_reg == src1) {
2930*22dc650dSSadaf Ebrahimi 			src1 = src2_reg;
2931*22dc650dSSadaf Ebrahimi 			src1w = 0;
2932*22dc650dSSadaf Ebrahimi 			type ^= 0x1;
2933*22dc650dSSadaf Ebrahimi 		} else {
2934*22dc650dSSadaf Ebrahimi 			if (ADDRESSING_DEPENDS_ON(src1, dst_reg)) {
2935*22dc650dSSadaf Ebrahimi 				FAIL_IF(push_inst(compiler, ADDI | RD(TMP_REG1) | RS1(dst_reg) | IMM_I(0)));
2936*22dc650dSSadaf Ebrahimi 
2937*22dc650dSSadaf Ebrahimi 				if ((src1 & REG_MASK) == dst_reg)
2938*22dc650dSSadaf Ebrahimi 					src1 = (src1 & ~REG_MASK) | TMP_REG1;
2939*22dc650dSSadaf Ebrahimi 
2940*22dc650dSSadaf Ebrahimi 				if (OFFS_REG(src1) == dst_reg)
2941*22dc650dSSadaf Ebrahimi 					src1 = (src1 & ~OFFS_REG_MASK) | TO_OFFS_REG(TMP_REG1);
2942*22dc650dSSadaf Ebrahimi 			}
2943*22dc650dSSadaf Ebrahimi 
2944*22dc650dSSadaf Ebrahimi 			FAIL_IF(push_inst(compiler, ADDI | WORD | RD(dst_reg) | RS1(src2_reg) | IMM_I(0)));
2945*22dc650dSSadaf Ebrahimi 		}
2946*22dc650dSSadaf Ebrahimi 	}
2947*22dc650dSSadaf Ebrahimi 
2948*22dc650dSSadaf Ebrahimi 	size = compiler->size;
2949*22dc650dSSadaf Ebrahimi 
2950*22dc650dSSadaf Ebrahimi 	ptr = (sljit_ins*)ensure_buf(compiler, sizeof(sljit_ins));
2951*22dc650dSSadaf Ebrahimi 	FAIL_IF(!ptr);
2952*22dc650dSSadaf Ebrahimi 	compiler->size++;
2953*22dc650dSSadaf Ebrahimi 
2954*22dc650dSSadaf Ebrahimi 	if (src1 & SLJIT_MEM) {
2955*22dc650dSSadaf Ebrahimi 		FAIL_IF(emit_op_mem(compiler, inp_flags, dst_reg, src1, src1w));
2956*22dc650dSSadaf Ebrahimi 	} else if (src1 == SLJIT_IMM) {
2957*22dc650dSSadaf Ebrahimi #if (defined SLJIT_CONFIG_RISCV_64 && SLJIT_CONFIG_RISCV_64)
2958*22dc650dSSadaf Ebrahimi 		if (word)
2959*22dc650dSSadaf Ebrahimi 			src1w = (sljit_s32)src1w;
2960*22dc650dSSadaf Ebrahimi #endif /* SLJIT_CONFIG_RISCV_64 */
2961*22dc650dSSadaf Ebrahimi 		FAIL_IF(load_immediate(compiler, dst_reg, src1w, TMP_REG1));
2962*22dc650dSSadaf Ebrahimi 	} else
2963*22dc650dSSadaf Ebrahimi 		FAIL_IF(push_inst(compiler, ADDI | WORD | RD(dst_reg) | RS1(src1) | IMM_I(0)));
2964*22dc650dSSadaf Ebrahimi 
2965*22dc650dSSadaf Ebrahimi 	size = compiler->size - size;
2966*22dc650dSSadaf Ebrahimi 	*ptr = get_jump_instruction(type & ~SLJIT_32) | (sljit_ins)((size & 0x7) << 9) | (sljit_ins)((size >> 3) << 25);
2967*22dc650dSSadaf Ebrahimi 	return SLJIT_SUCCESS;
2968*22dc650dSSadaf Ebrahimi }
2969*22dc650dSSadaf Ebrahimi 
2970*22dc650dSSadaf Ebrahimi #undef WORD
2971*22dc650dSSadaf Ebrahimi 
sljit_emit_fselect(struct sljit_compiler * compiler,sljit_s32 type,sljit_s32 dst_freg,sljit_s32 src1,sljit_sw src1w,sljit_s32 src2_freg)2972*22dc650dSSadaf Ebrahimi SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fselect(struct sljit_compiler *compiler, sljit_s32 type,
2973*22dc650dSSadaf Ebrahimi 	sljit_s32 dst_freg,
2974*22dc650dSSadaf Ebrahimi 	sljit_s32 src1, sljit_sw src1w,
2975*22dc650dSSadaf Ebrahimi 	sljit_s32 src2_freg)
2976*22dc650dSSadaf Ebrahimi {
2977*22dc650dSSadaf Ebrahimi 	sljit_ins *ptr;
2978*22dc650dSSadaf Ebrahimi 	sljit_uw size;
2979*22dc650dSSadaf Ebrahimi 
2980*22dc650dSSadaf Ebrahimi 	CHECK_ERROR();
2981*22dc650dSSadaf Ebrahimi 	CHECK(check_sljit_emit_fselect(compiler, type, dst_freg, src1, src1w, src2_freg));
2982*22dc650dSSadaf Ebrahimi 
2983*22dc650dSSadaf Ebrahimi 	ADJUST_LOCAL_OFFSET(src1, src1w);
2984*22dc650dSSadaf Ebrahimi 
2985*22dc650dSSadaf Ebrahimi 	if (dst_freg != src2_freg) {
2986*22dc650dSSadaf Ebrahimi 		if (dst_freg == src1) {
2987*22dc650dSSadaf Ebrahimi 			src1 = src2_freg;
2988*22dc650dSSadaf Ebrahimi 			src1w = 0;
2989*22dc650dSSadaf Ebrahimi 			type ^= 0x1;
2990*22dc650dSSadaf Ebrahimi 		} else
2991*22dc650dSSadaf Ebrahimi 			FAIL_IF(push_inst(compiler, FSGNJ_S | FMT(type) | FRD(dst_freg) | FRS1(src2_freg) | FRS2(src2_freg)));
2992*22dc650dSSadaf Ebrahimi 	}
2993*22dc650dSSadaf Ebrahimi 
2994*22dc650dSSadaf Ebrahimi 	size = compiler->size;
2995*22dc650dSSadaf Ebrahimi 
2996*22dc650dSSadaf Ebrahimi 	ptr = (sljit_ins*)ensure_buf(compiler, sizeof(sljit_ins));
2997*22dc650dSSadaf Ebrahimi 	FAIL_IF(!ptr);
2998*22dc650dSSadaf Ebrahimi 	compiler->size++;
2999*22dc650dSSadaf Ebrahimi 
3000*22dc650dSSadaf Ebrahimi 	if (src1 & SLJIT_MEM)
3001*22dc650dSSadaf Ebrahimi 		FAIL_IF(emit_op_mem(compiler, FLOAT_DATA(type) | LOAD_DATA, dst_freg, src1, src1w));
3002*22dc650dSSadaf Ebrahimi 	else
3003*22dc650dSSadaf Ebrahimi 		FAIL_IF(push_inst(compiler, FSGNJ_S | FMT(type) | FRD(dst_freg) | FRS1(src1) | FRS2(src1)));
3004*22dc650dSSadaf Ebrahimi 
3005*22dc650dSSadaf Ebrahimi 	size = compiler->size - size;
3006*22dc650dSSadaf Ebrahimi 	*ptr = get_jump_instruction(type & ~SLJIT_32) | (sljit_ins)((size & 0x7) << 9) | (sljit_ins)((size >> 3) << 25);
3007*22dc650dSSadaf Ebrahimi 	return SLJIT_SUCCESS;
3008*22dc650dSSadaf Ebrahimi }
3009*22dc650dSSadaf Ebrahimi 
3010*22dc650dSSadaf Ebrahimi #undef FLOAT_DATA
3011*22dc650dSSadaf Ebrahimi #undef FMT
3012*22dc650dSSadaf Ebrahimi 
sljit_emit_mem(struct sljit_compiler * compiler,sljit_s32 type,sljit_s32 reg,sljit_s32 mem,sljit_sw memw)3013*22dc650dSSadaf Ebrahimi SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_mem(struct sljit_compiler *compiler, sljit_s32 type,
3014*22dc650dSSadaf Ebrahimi 	sljit_s32 reg,
3015*22dc650dSSadaf Ebrahimi 	sljit_s32 mem, sljit_sw memw)
3016*22dc650dSSadaf Ebrahimi {
3017*22dc650dSSadaf Ebrahimi 	sljit_s32 flags;
3018*22dc650dSSadaf Ebrahimi 
3019*22dc650dSSadaf Ebrahimi 	CHECK_ERROR();
3020*22dc650dSSadaf Ebrahimi 	CHECK(check_sljit_emit_mem(compiler, type, reg, mem, memw));
3021*22dc650dSSadaf Ebrahimi 
3022*22dc650dSSadaf Ebrahimi 	if (!(reg & REG_PAIR_MASK))
3023*22dc650dSSadaf Ebrahimi 		return sljit_emit_mem_unaligned(compiler, type, reg, mem, memw);
3024*22dc650dSSadaf Ebrahimi 
3025*22dc650dSSadaf Ebrahimi 	if (SLJIT_UNLIKELY(mem & OFFS_REG_MASK)) {
3026*22dc650dSSadaf Ebrahimi 		memw &= 0x3;
3027*22dc650dSSadaf Ebrahimi 
3028*22dc650dSSadaf Ebrahimi 		if (SLJIT_UNLIKELY(memw != 0)) {
3029*22dc650dSSadaf Ebrahimi 			FAIL_IF(push_inst(compiler, SLLI | RD(TMP_REG1) | RS1(OFFS_REG(mem)) | IMM_I(memw)));
3030*22dc650dSSadaf Ebrahimi 			FAIL_IF(push_inst(compiler, ADD | RD(TMP_REG1) | RS1(TMP_REG1) | RS2(mem & REG_MASK)));
3031*22dc650dSSadaf Ebrahimi 		} else
3032*22dc650dSSadaf Ebrahimi 			FAIL_IF(push_inst(compiler, ADD | RD(TMP_REG1) | RS1(mem & REG_MASK) | RS2(OFFS_REG(mem))));
3033*22dc650dSSadaf Ebrahimi 
3034*22dc650dSSadaf Ebrahimi 		mem = TMP_REG1;
3035*22dc650dSSadaf Ebrahimi 		memw = 0;
3036*22dc650dSSadaf Ebrahimi 	} else if (memw > SIMM_MAX - SSIZE_OF(sw) || memw < SIMM_MIN) {
3037*22dc650dSSadaf Ebrahimi 		if (((memw + 0x800) & 0xfff) <= 0xfff - SSIZE_OF(sw)) {
3038*22dc650dSSadaf Ebrahimi 			FAIL_IF(load_immediate(compiler, TMP_REG1, TO_ARGW_HI(memw), TMP_REG3));
3039*22dc650dSSadaf Ebrahimi 			memw &= 0xfff;
3040*22dc650dSSadaf Ebrahimi 		} else {
3041*22dc650dSSadaf Ebrahimi 			FAIL_IF(load_immediate(compiler, TMP_REG1, memw, TMP_REG3));
3042*22dc650dSSadaf Ebrahimi 			memw = 0;
3043*22dc650dSSadaf Ebrahimi 		}
3044*22dc650dSSadaf Ebrahimi 
3045*22dc650dSSadaf Ebrahimi 		if (mem & REG_MASK)
3046*22dc650dSSadaf Ebrahimi 			FAIL_IF(push_inst(compiler, ADD | RD(TMP_REG1) | RS1(TMP_REG1) | RS2(mem & REG_MASK)));
3047*22dc650dSSadaf Ebrahimi 
3048*22dc650dSSadaf Ebrahimi 		mem = TMP_REG1;
3049*22dc650dSSadaf Ebrahimi 	} else {
3050*22dc650dSSadaf Ebrahimi 		mem &= REG_MASK;
3051*22dc650dSSadaf Ebrahimi 		memw &= 0xfff;
3052*22dc650dSSadaf Ebrahimi 	}
3053*22dc650dSSadaf Ebrahimi 
3054*22dc650dSSadaf Ebrahimi 	SLJIT_ASSERT((memw >= 0 && memw <= SIMM_MAX - SSIZE_OF(sw)) || (memw > SIMM_MAX && memw <= 0xfff));
3055*22dc650dSSadaf Ebrahimi 
3056*22dc650dSSadaf Ebrahimi 	if (!(type & SLJIT_MEM_STORE) && mem == REG_PAIR_FIRST(reg)) {
3057*22dc650dSSadaf Ebrahimi 		FAIL_IF(push_mem_inst(compiler, WORD_DATA | LOAD_DATA, REG_PAIR_SECOND(reg), mem, (memw + SSIZE_OF(sw)) & 0xfff));
3058*22dc650dSSadaf Ebrahimi 		return push_mem_inst(compiler, WORD_DATA | LOAD_DATA, REG_PAIR_FIRST(reg), mem, memw);
3059*22dc650dSSadaf Ebrahimi 	}
3060*22dc650dSSadaf Ebrahimi 
3061*22dc650dSSadaf Ebrahimi 	flags = WORD_DATA | (!(type & SLJIT_MEM_STORE) ? LOAD_DATA : 0);
3062*22dc650dSSadaf Ebrahimi 
3063*22dc650dSSadaf Ebrahimi 	FAIL_IF(push_mem_inst(compiler, flags, REG_PAIR_FIRST(reg), mem, memw));
3064*22dc650dSSadaf Ebrahimi 	return push_mem_inst(compiler, flags, REG_PAIR_SECOND(reg), mem, (memw + SSIZE_OF(sw)) & 0xfff);
3065*22dc650dSSadaf Ebrahimi }
3066*22dc650dSSadaf Ebrahimi 
3067*22dc650dSSadaf Ebrahimi #undef TO_ARGW_HI
3068*22dc650dSSadaf Ebrahimi 
sljit_emit_const(struct sljit_compiler * compiler,sljit_s32 dst,sljit_sw dstw,sljit_sw init_value)3069*22dc650dSSadaf Ebrahimi SLJIT_API_FUNC_ATTRIBUTE struct sljit_const* sljit_emit_const(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw dstw, sljit_sw init_value)
3070*22dc650dSSadaf Ebrahimi {
3071*22dc650dSSadaf Ebrahimi 	struct sljit_const *const_;
3072*22dc650dSSadaf Ebrahimi 	sljit_s32 dst_r;
3073*22dc650dSSadaf Ebrahimi 
3074*22dc650dSSadaf Ebrahimi 	CHECK_ERROR_PTR();
3075*22dc650dSSadaf Ebrahimi 	CHECK_PTR(check_sljit_emit_const(compiler, dst, dstw, init_value));
3076*22dc650dSSadaf Ebrahimi 	ADJUST_LOCAL_OFFSET(dst, dstw);
3077*22dc650dSSadaf Ebrahimi 
3078*22dc650dSSadaf Ebrahimi 	const_ = (struct sljit_const*)ensure_abuf(compiler, sizeof(struct sljit_const));
3079*22dc650dSSadaf Ebrahimi 	PTR_FAIL_IF(!const_);
3080*22dc650dSSadaf Ebrahimi 	set_const(const_, compiler);
3081*22dc650dSSadaf Ebrahimi 
3082*22dc650dSSadaf Ebrahimi 	dst_r = FAST_IS_REG(dst) ? dst : TMP_REG2;
3083*22dc650dSSadaf Ebrahimi 	PTR_FAIL_IF(emit_const(compiler, dst_r, init_value, ADDI | RD(dst_r)));
3084*22dc650dSSadaf Ebrahimi 
3085*22dc650dSSadaf Ebrahimi 	if (dst & SLJIT_MEM)
3086*22dc650dSSadaf Ebrahimi 		PTR_FAIL_IF(emit_op_mem(compiler, WORD_DATA, TMP_REG2, dst, dstw));
3087*22dc650dSSadaf Ebrahimi 
3088*22dc650dSSadaf Ebrahimi 	return const_;
3089*22dc650dSSadaf Ebrahimi }
3090*22dc650dSSadaf Ebrahimi 
sljit_emit_mov_addr(struct sljit_compiler * compiler,sljit_s32 dst,sljit_sw dstw)3091*22dc650dSSadaf Ebrahimi SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_mov_addr(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw dstw)
3092*22dc650dSSadaf Ebrahimi {
3093*22dc650dSSadaf Ebrahimi 	struct sljit_jump *jump;
3094*22dc650dSSadaf Ebrahimi 	sljit_s32 dst_r;
3095*22dc650dSSadaf Ebrahimi 
3096*22dc650dSSadaf Ebrahimi 	CHECK_ERROR_PTR();
3097*22dc650dSSadaf Ebrahimi 	CHECK_PTR(check_sljit_emit_mov_addr(compiler, dst, dstw));
3098*22dc650dSSadaf Ebrahimi 	ADJUST_LOCAL_OFFSET(dst, dstw);
3099*22dc650dSSadaf Ebrahimi 
3100*22dc650dSSadaf Ebrahimi 	jump = (struct sljit_jump*)ensure_abuf(compiler, sizeof(struct sljit_jump));
3101*22dc650dSSadaf Ebrahimi 	PTR_FAIL_IF(!jump);
3102*22dc650dSSadaf Ebrahimi 	set_mov_addr(jump, compiler, 0);
3103*22dc650dSSadaf Ebrahimi 
3104*22dc650dSSadaf Ebrahimi 	dst_r = FAST_IS_REG(dst) ? dst : TMP_REG2;
3105*22dc650dSSadaf Ebrahimi 	PTR_FAIL_IF(push_inst(compiler, (sljit_ins)dst_r));
3106*22dc650dSSadaf Ebrahimi #if (defined SLJIT_CONFIG_RISCV_32 && SLJIT_CONFIG_RISCV_32)
3107*22dc650dSSadaf Ebrahimi 	compiler->size += 1;
3108*22dc650dSSadaf Ebrahimi #else /* !SLJIT_CONFIG_RISCV_32 */
3109*22dc650dSSadaf Ebrahimi 	compiler->size += 5;
3110*22dc650dSSadaf Ebrahimi #endif /* SLJIT_CONFIG_RISCV_32 */
3111*22dc650dSSadaf Ebrahimi 
3112*22dc650dSSadaf Ebrahimi 	if (dst & SLJIT_MEM)
3113*22dc650dSSadaf Ebrahimi 		PTR_FAIL_IF(emit_op_mem(compiler, WORD_DATA, TMP_REG2, dst, dstw));
3114*22dc650dSSadaf Ebrahimi 
3115*22dc650dSSadaf Ebrahimi 	return jump;
3116*22dc650dSSadaf Ebrahimi }
3117*22dc650dSSadaf Ebrahimi 
sljit_set_const(sljit_uw addr,sljit_sw new_constant,sljit_sw executable_offset)3118*22dc650dSSadaf Ebrahimi SLJIT_API_FUNC_ATTRIBUTE void sljit_set_const(sljit_uw addr, sljit_sw new_constant, sljit_sw executable_offset)
3119*22dc650dSSadaf Ebrahimi {
3120*22dc650dSSadaf Ebrahimi 	sljit_set_jump_addr(addr, (sljit_uw)new_constant, executable_offset);
3121*22dc650dSSadaf Ebrahimi }
3122