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