Path: blob/master/thirdparty/pcre2/deps/sljit/sljit_src/sljitNativeRISCV_common.c
9913 views
/*1* Stack-less Just-In-Time compiler2*3* Copyright Zoltan Herczeg ([email protected]). All rights reserved.4*5* Redistribution and use in source and binary forms, with or without modification, are6* permitted provided that the following conditions are met:7*8* 1. Redistributions of source code must retain the above copyright notice, this list of9* conditions and the following disclaimer.10*11* 2. Redistributions in binary form must reproduce the above copyright notice, this list12* of conditions and the following disclaimer in the documentation and/or other materials13* provided with the distribution.14*15* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) AND CONTRIBUTORS ``AS IS'' AND ANY16* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES17* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT18* SHALL THE COPYRIGHT HOLDER(S) OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,19* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED20* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR21* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN22* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN23* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.24*/2526SLJIT_API_FUNC_ATTRIBUTE const char* sljit_get_platform_name(void)27{28#if (defined SLJIT_CONFIG_RISCV_32 && SLJIT_CONFIG_RISCV_32)29return "RISC-V-32" SLJIT_CPUINFO;30#else /* !SLJIT_CONFIG_RISCV_32 */31return "RISC-V-64" SLJIT_CPUINFO;32#endif /* SLJIT_CONFIG_RISCV_32 */33}3435/* Length of an instruction word36Both for riscv-32 and riscv-64 */37typedef sljit_u32 sljit_ins;3839#define TMP_REG1 (SLJIT_NUMBER_OF_REGISTERS + 2)40#define TMP_REG2 (SLJIT_NUMBER_OF_REGISTERS + 3)41#define TMP_REG3 (SLJIT_NUMBER_OF_REGISTERS + 4)42#define TMP_ZERO 04344/* Flags are kept in volatile registers. */45#define EQUAL_FLAG (SLJIT_NUMBER_OF_REGISTERS + 5)46#define RETURN_ADDR_REG TMP_REG247#define OTHER_FLAG (SLJIT_NUMBER_OF_REGISTERS + 6)4849#define TMP_FREG1 (SLJIT_NUMBER_OF_FLOAT_REGISTERS + 1)50#define TMP_FREG2 (SLJIT_NUMBER_OF_FLOAT_REGISTERS + 2)5152#define TMP_VREG1 (SLJIT_NUMBER_OF_VECTOR_REGISTERS + 1)53#define TMP_VREG2 (SLJIT_NUMBER_OF_VECTOR_REGISTERS + 2)5455static const sljit_u8 reg_map[SLJIT_NUMBER_OF_REGISTERS + 7] = {560, 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, 2857};5859static const sljit_u8 freg_map[SLJIT_NUMBER_OF_FLOAT_REGISTERS + 3] = {600, 10, 11, 12, 13, 14, 15, 16, 17, 2, 3, 4, 5, 6, 7, 28, 29, 30, 31, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 9, 8, 0, 1,61};6263static const sljit_u8 vreg_map[SLJIT_NUMBER_OF_VECTOR_REGISTERS + 3] = {640, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 3165};6667/* --------------------------------------------------------------------- */68/* Instrucion forms */69/* --------------------------------------------------------------------- */7071#define RD(rd) ((sljit_ins)reg_map[rd] << 7)72#define RS1(rs1) ((sljit_ins)reg_map[rs1] << 15)73#define RS2(rs2) ((sljit_ins)reg_map[rs2] << 20)74#define FRD(rd) ((sljit_ins)freg_map[rd] << 7)75#define FRS1(rs1) ((sljit_ins)freg_map[rs1] << 15)76#define FRS2(rs2) ((sljit_ins)freg_map[rs2] << 20)77#define VRD(rd) ((sljit_ins)vreg_map[rd] << 7)78#define VRS1(rs1) ((sljit_ins)vreg_map[rs1] << 15)79#define VRS2(rs2) ((sljit_ins)vreg_map[rs2] << 20)80#define IMM_I(imm) ((sljit_ins)(imm) << 20)81#define IMM_S(imm) ((((sljit_ins)(imm) & 0xfe0) << 20) | (((sljit_ins)(imm) & 0x1f) << 7))8283/* Represents funct(i) parts of the instructions. */84#define OPC(o) ((sljit_ins)(o))85#define F3(f) ((sljit_ins)(f) << 12)86#define F12(f) ((sljit_ins)(f) << 20)87#define F7(f) ((sljit_ins)(f) << 25)8889/* Vector instruction types. */90#define OPFVF (F3(0x5) | OPC(0x57))91#define OPFVV (F3(0x1) | OPC(0x57))92#define OPIVI (F3(0x3) | OPC(0x57))93#define OPIVV (F3(0x0) | OPC(0x57))94#define OPIVX (F3(0x4) | OPC(0x57))95#define OPMVV (F3(0x2) | OPC(0x57))96#define OPMVX (F3(0x6) | OPC(0x57))9798#define ADD (F7(0x0) | F3(0x0) | OPC(0x33))99#define ADDI (F3(0x0) | OPC(0x13))100#define AND (F7(0x0) | F3(0x7) | OPC(0x33))101#define ANDI (F3(0x7) | OPC(0x13))102#define AUIPC (OPC(0x17))103#define BEQ (F3(0x0) | OPC(0x63))104#define BNE (F3(0x1) | OPC(0x63))105#define BLT (F3(0x4) | OPC(0x63))106#define BGE (F3(0x5) | OPC(0x63))107#define BLTU (F3(0x6) | OPC(0x63))108#define BGEU (F3(0x7) | OPC(0x63))109#if defined __riscv_zbb110#define CLZ (F7(0x30) | F3(0x1) | OPC(0x13))111#define CTZ (F7(0x30) | F12(0x1) | F3(0x1) | OPC(0x13))112#endif /* __riscv_zbb */113#define DIV (F7(0x1) | F3(0x4) | OPC(0x33))114#define DIVU (F7(0x1) | F3(0x5) | OPC(0x33))115#define EBREAK (F12(0x1) | F3(0x0) | OPC(0x73))116#define FADD_S (F7(0x0) | F3(0x7) | OPC(0x53))117#define FDIV_S (F7(0xc) | F3(0x7) | OPC(0x53))118#define FENCE (F3(0x0) | OPC(0xf))119#define FEQ_S (F7(0x50) | F3(0x2) | OPC(0x53))120#define FLD (F3(0x3) | OPC(0x7))121#define FLE_S (F7(0x50) | F3(0x0) | OPC(0x53))122#define FLT_S (F7(0x50) | F3(0x1) | OPC(0x53))123/* These conversion opcodes are partly defined. */124#define FCVT_S_D (F7(0x20) | OPC(0x53))125#define FCVT_S_W (F7(0x68) | OPC(0x53))126#define FCVT_S_WU (F7(0x68) | F12(0x1) | OPC(0x53))127#define FCVT_W_S (F7(0x60) | F3(0x1) | OPC(0x53))128#define FMUL_S (F7(0x8) | F3(0x7) | OPC(0x53))129#define FMV_X_W (F7(0x70) | F3(0x0) | OPC(0x53))130#define FMV_W_X (F7(0x78) | F3(0x0) | OPC(0x53))131#define FSD (F3(0x3) | OPC(0x27))132#define FSGNJ_S (F7(0x10) | F3(0x0) | OPC(0x53))133#define FSGNJN_S (F7(0x10) | F3(0x1) | OPC(0x53))134#define FSGNJX_S (F7(0x10) | F3(0x2) | OPC(0x53))135#define FSUB_S (F7(0x4) | F3(0x7) | OPC(0x53))136#define FSW (F3(0x2) | OPC(0x27))137#define JAL (OPC(0x6f))138#define JALR (F3(0x0) | OPC(0x67))139#define LD (F3(0x3) | OPC(0x3))140#define LUI (OPC(0x37))141#define LW (F3(0x2) | OPC(0x3))142#define LR (F7(0x8) | OPC(0x2f))143#define MUL (F7(0x1) | F3(0x0) | OPC(0x33))144#define MULH (F7(0x1) | F3(0x1) | OPC(0x33))145#define MULHU (F7(0x1) | F3(0x3) | OPC(0x33))146#define OR (F7(0x0) | F3(0x6) | OPC(0x33))147#define ORI (F3(0x6) | OPC(0x13))148#define REM (F7(0x1) | F3(0x6) | OPC(0x33))149#define REMU (F7(0x1) | F3(0x7) | OPC(0x33))150#if defined __riscv_zbb151#if defined SLJIT_CONFIG_RISCV_32152#define REV8 (F12(0x698) | F3(0x5) | OPC(0x13))153#elif defined SLJIT_CONFIG_RISCV_64154#define REV8 (F12(0x6b8) | F3(0x5) | OPC(0x13))155#endif /* SLJIT_CONFIG_RISCV_32 */156#define ROL (F7(0x30) | F3(0x1) | OPC(0x33))157#define ROR (F7(0x30) | F3(0x5) | OPC(0x33))158#define RORI (F7(0x30) | F3(0x5) | OPC(0x13))159#endif /* __riscv_zbb */160#define SC (F7(0xc) | OPC(0x2f))161#define SD (F3(0x3) | OPC(0x23))162#if defined __riscv_zbb163#define SEXTB (F7(0x30) | F12(0x4) | F3(0x1) | OPC(0x13))164#define SEXTH (F7(0x30) | F12(0x5) | F3(0x1) | OPC(0x13))165#endif /* __riscv_zbb */166#if defined __riscv_zba167#define SH1ADD (F7(0x10) | F3(0x2) | OPC(0x33))168#define SH2ADD (F7(0x10) | F3(0x4) | OPC(0x33))169#define SH3ADD (F7(0x10) | F3(0x6) | OPC(0x33))170#endif /* __riscv_zba */171#define SLL (F7(0x0) | F3(0x1) | OPC(0x33))172#define SLLI (F3(0x1) | OPC(0x13))173#define SLT (F7(0x0) | F3(0x2) | OPC(0x33))174#define SLTI (F3(0x2) | OPC(0x13))175#define SLTU (F7(0x0) | F3(0x3) | OPC(0x33))176#define SLTUI (F3(0x3) | OPC(0x13))177#define SRL (F7(0x0) | F3(0x5) | OPC(0x33))178#define SRLI (F3(0x5) | OPC(0x13))179#define SRA (F7(0x20) | F3(0x5) | OPC(0x33))180#define SRAI (F7(0x20) | F3(0x5) | OPC(0x13))181#define SUB (F7(0x20) | F3(0x0) | OPC(0x33))182#define SW (F3(0x2) | OPC(0x23))183#define VAND_VV (F7(0x13) | OPIVV)184#define VFMV_FS (F7(0x21) | OPFVV)185#define VFMV_SF (F7(0x21) | OPFVF)186#define VFMV_VF (F7(0x2f) | OPFVF)187#define VFWCVT_FFV (F7(0x25) | (0xc << 15) | OPFVV)188#define VL (F7(0x1) | OPC(0x7))189#define VMSLE_VI (F7(0x3b) | OPIVI)190#define VMV_SX (F7(0x21) | OPMVX)191#define VMV_VI (F7(0x2f) | OPIVI)192#define VMV_VV (F7(0x2f) | OPIVV)193#define VMV_VX (F7(0x2f) | OPIVX)194#define VMV_XS (F7(0x21) | OPMVV)195#define VOR_VV (F7(0x15) | OPIVV)196#define VSETIVLI (F7(0x60) | F3(0x7) | OPC(0x57))197#define VS (F7(0x1) | OPC(0x27))198#define VSLIDEDOWN_VX (F7(0x1f) | OPIVX)199#define VSLIDEDOWN_VI (F7(0x1f) | OPIVI)200#define VSLIDEUP_VX (F7(0x1d) | OPIVX)201#define VSLIDEUP_VI (F7(0x1d) | OPIVI)202#define VRGATHER_VI (F7(0x19) | OPIVI)203#define VRGATHER_VV (F7(0x19) | OPIVV)204#define VXOR_VV (F7(0x17) | OPIVV)205#define VZEXT_VF2 (F7(0x25) | (0x6 << 15) | OPMVV)206#define VZEXT_VF4 (F7(0x25) | (0x4 << 15) | OPMVV)207#define VZEXT_VF8 (F7(0x25) | (0x2 << 15) | OPMVV)208#define XOR (F7(0x0) | F3(0x4) | OPC(0x33))209#define XORI (F3(0x4) | OPC(0x13))210#if defined __riscv_zbb211#if defined SLJIT_CONFIG_RISCV_32212#define ZEXTH (F7(0x4) | F3(0x4) | OPC(0x33))213#elif defined SLJIT_CONFIG_RISCV_64214#define ZEXTH (F7(0x4) | F3(0x4) | OPC(0x3B))215#endif /* SLJIT_CONFIG_RISCV_32 */216#endif /* __riscv_zbb */217218#define SIMM_MAX (0x7ff)219#define SIMM_MIN (-0x800)220#define BRANCH_MAX (0xfff)221#define BRANCH_MIN (-0x1000)222#define JUMP_MAX (0xfffff)223#define JUMP_MIN (-0x100000)224225#if (defined SLJIT_CONFIG_RISCV_64 && SLJIT_CONFIG_RISCV_64)226#define S32_MAX (0x7ffff7ffl)227#define S32_MIN (-0x80000000l)228#define S44_MAX (0x7fffffff7ffl)229#define S52_MAX (0x7ffffffffffffl)230#endif /* SLJIT_CONFIG_RISCV_64 */231232static sljit_s32 push_inst(struct sljit_compiler *compiler, sljit_ins ins)233{234sljit_ins *ptr = (sljit_ins*)ensure_buf(compiler, sizeof(sljit_ins));235FAIL_IF(!ptr);236*ptr = ins;237compiler->size++;238return SLJIT_SUCCESS;239}240241static sljit_s32 push_imm_s_inst(struct sljit_compiler *compiler, sljit_ins ins, sljit_sw imm)242{243return push_inst(compiler, ins | IMM_S(imm));244}245246static SLJIT_INLINE sljit_ins* detect_jump_type(struct sljit_jump *jump, sljit_ins *code_ptr, sljit_ins *code, sljit_sw executable_offset)247{248sljit_sw diff;249sljit_uw target_addr;250sljit_uw jump_addr = (sljit_uw)code_ptr;251sljit_uw orig_addr = jump->addr;252SLJIT_UNUSED_ARG(executable_offset);253254jump->addr = jump_addr;255if (jump->flags & SLJIT_REWRITABLE_JUMP)256goto exit;257258if (jump->flags & JUMP_ADDR)259target_addr = jump->u.target;260else {261SLJIT_ASSERT(jump->u.label != NULL);262target_addr = (sljit_uw)SLJIT_ADD_EXEC_OFFSET(code + jump->u.label->size, executable_offset);263264if (jump->u.label->size > orig_addr)265jump_addr = (sljit_uw)(code + orig_addr);266}267268diff = (sljit_sw)target_addr - (sljit_sw)SLJIT_ADD_EXEC_OFFSET(jump_addr, executable_offset);269270if (jump->flags & IS_COND) {271diff += SSIZE_OF(ins);272273if (diff >= BRANCH_MIN && diff <= BRANCH_MAX) {274code_ptr--;275code_ptr[0] = (code_ptr[0] & 0x1fff07f) ^ 0x1000;276jump->flags |= PATCH_B;277jump->addr = (sljit_uw)code_ptr;278return code_ptr;279}280281diff -= SSIZE_OF(ins);282}283284if (diff >= JUMP_MIN && diff <= JUMP_MAX) {285if (jump->flags & IS_COND) {286#if (defined SLJIT_CONFIG_RISCV_32 && SLJIT_CONFIG_RISCV_32)287code_ptr[-1] -= (sljit_ins)(1 * sizeof(sljit_ins)) << 7;288#else /* !SLJIT_CONFIG_RISCV_32 */289code_ptr[-1] -= (sljit_ins)(5 * sizeof(sljit_ins)) << 7;290#endif /* SLJIT_CONFIG_RISCV_32 */291}292293jump->flags |= PATCH_J;294return code_ptr;295}296297#if (defined SLJIT_CONFIG_RISCV_64 && SLJIT_CONFIG_RISCV_64)298if (diff >= S32_MIN && diff <= S32_MAX) {299if (jump->flags & IS_COND)300code_ptr[-1] -= (sljit_ins)(4 * sizeof(sljit_ins)) << 7;301302jump->flags |= PATCH_REL32;303code_ptr[1] = code_ptr[0];304return code_ptr + 1;305}306307if (target_addr <= (sljit_uw)S32_MAX) {308if (jump->flags & IS_COND)309code_ptr[-1] -= (sljit_ins)(4 * sizeof(sljit_ins)) << 7;310311jump->flags |= PATCH_ABS32;312code_ptr[1] = code_ptr[0];313return code_ptr + 1;314}315316if (target_addr <= S44_MAX) {317if (jump->flags & IS_COND)318code_ptr[-1] -= (sljit_ins)(2 * sizeof(sljit_ins)) << 7;319320jump->flags |= PATCH_ABS44;321code_ptr[3] = code_ptr[0];322return code_ptr + 3;323}324325if (target_addr <= S52_MAX) {326if (jump->flags & IS_COND)327code_ptr[-1] -= (sljit_ins)(1 * sizeof(sljit_ins)) << 7;328329jump->flags |= PATCH_ABS52;330code_ptr[4] = code_ptr[0];331return code_ptr + 4;332}333#endif /* SLJIT_CONFIG_RISCV_64 */334335exit:336#if (defined SLJIT_CONFIG_RISCV_32 && SLJIT_CONFIG_RISCV_32)337code_ptr[1] = code_ptr[0];338return code_ptr + 1;339#else /* !SLJIT_CONFIG_RISCV_32 */340code_ptr[5] = code_ptr[0];341return code_ptr + 5;342#endif /* SLJIT_CONFIG_RISCV_32 */343}344345#if (defined SLJIT_CONFIG_RISCV_64 && SLJIT_CONFIG_RISCV_64)346347static SLJIT_INLINE sljit_sw mov_addr_get_length(struct sljit_jump *jump, sljit_ins *code_ptr, sljit_ins *code, sljit_sw executable_offset)348{349sljit_uw addr;350sljit_uw jump_addr = (sljit_uw)code_ptr;351sljit_sw diff;352SLJIT_UNUSED_ARG(executable_offset);353354SLJIT_ASSERT(jump->flags < ((sljit_uw)6 << JUMP_SIZE_SHIFT));355if (jump->flags & JUMP_ADDR)356addr = jump->u.target;357else {358addr = (sljit_uw)SLJIT_ADD_EXEC_OFFSET(code + jump->u.label->size, executable_offset);359360if (jump->u.label->size > jump->addr)361jump_addr = (sljit_uw)(code + jump->addr);362}363364diff = (sljit_sw)addr - (sljit_sw)SLJIT_ADD_EXEC_OFFSET(jump_addr, executable_offset);365366if (diff >= S32_MIN && diff <= S32_MAX) {367SLJIT_ASSERT(jump->flags >= ((sljit_uw)1 << JUMP_SIZE_SHIFT));368jump->flags |= PATCH_REL32;369return 1;370}371372if (addr <= S32_MAX) {373SLJIT_ASSERT(jump->flags >= ((sljit_uw)1 << JUMP_SIZE_SHIFT));374jump->flags |= PATCH_ABS32;375return 1;376}377378if (addr <= S44_MAX) {379SLJIT_ASSERT(jump->flags >= ((sljit_uw)3 << JUMP_SIZE_SHIFT));380jump->flags |= PATCH_ABS44;381return 3;382}383384if (addr <= S52_MAX) {385SLJIT_ASSERT(jump->flags >= ((sljit_uw)4 << JUMP_SIZE_SHIFT));386jump->flags |= PATCH_ABS52;387return 4;388}389390SLJIT_ASSERT(jump->flags >= ((sljit_uw)5 << JUMP_SIZE_SHIFT));391return 5;392}393394#endif /* SLJIT_CONFIG_RISCV_64 */395396static SLJIT_INLINE void load_addr_to_reg(struct sljit_jump *jump, sljit_sw executable_offset)397{398sljit_uw flags = jump->flags;399sljit_uw addr = (flags & JUMP_ADDR) ? jump->u.target : jump->u.label->u.addr;400sljit_ins *ins = (sljit_ins*)jump->addr;401sljit_u32 reg = (flags & JUMP_MOV_ADDR) ? *ins : TMP_REG1;402#if (defined SLJIT_CONFIG_RISCV_64 && SLJIT_CONFIG_RISCV_64)403sljit_sw high;404#endif /* SLJIT_CONFIG_RISCV_64 */405SLJIT_UNUSED_ARG(executable_offset);406407#if (defined SLJIT_CONFIG_RISCV_64 && SLJIT_CONFIG_RISCV_64)408if (flags & PATCH_REL32) {409addr -= (sljit_uw)SLJIT_ADD_EXEC_OFFSET(ins, executable_offset);410411SLJIT_ASSERT((sljit_sw)addr >= S32_MIN && (sljit_sw)addr <= S32_MAX);412413if ((addr & 0x800) != 0)414addr += 0x1000;415416ins[0] = AUIPC | RD(reg) | (sljit_ins)((sljit_sw)addr & ~0xfff);417418if (!(flags & JUMP_MOV_ADDR)) {419SLJIT_ASSERT((ins[1] & 0x707f) == JALR);420ins[1] = (ins[1] & 0xfffff) | IMM_I(addr);421} else422ins[1] = ADDI | RD(reg) | RS1(reg) | IMM_I(addr);423return;424}425#endif /* SLJIT_CONFIG_RISCV_64 */426427if ((addr & 0x800) != 0)428addr += 0x1000;429430#if (defined SLJIT_CONFIG_RISCV_32 && SLJIT_CONFIG_RISCV_32)431ins[0] = LUI | RD(reg) | (sljit_ins)((sljit_sw)addr & ~0xfff);432#else /* !SLJIT_CONFIG_RISCV_32 */433434if (flags & PATCH_ABS32) {435SLJIT_ASSERT(addr <= S32_MAX);436ins[0] = LUI | RD(reg) | (sljit_ins)((sljit_sw)addr & ~0xfff);437} else if (flags & PATCH_ABS44) {438high = (sljit_sw)addr >> 12;439SLJIT_ASSERT((sljit_uw)high <= 0x7fffffff);440441if (high > S32_MAX) {442SLJIT_ASSERT((high & 0x800) != 0);443ins[0] = LUI | RD(reg) | (sljit_ins)0x80000000u;444ins[1] = XORI | RD(reg) | RS1(reg) | IMM_I(high);445} else {446if ((high & 0x800) != 0)447high += 0x1000;448449ins[0] = LUI | RD(reg) | (sljit_ins)(high & ~0xfff);450ins[1] = ADDI | RD(reg) | RS1(reg) | IMM_I(high);451}452453ins[2] = SLLI | RD(reg) | RS1(reg) | IMM_I(12);454ins += 2;455} else {456high = (sljit_sw)addr >> 32;457458if ((addr & 0x80000000l) != 0)459high = ~high;460461if (flags & PATCH_ABS52) {462SLJIT_ASSERT(addr <= S52_MAX);463ins[0] = LUI | RD(TMP_REG3) | (sljit_ins)(high << 12);464} else {465if ((high & 0x800) != 0)466high += 0x1000;467ins[0] = LUI | RD(TMP_REG3) | (sljit_ins)(high & ~0xfff);468ins[1] = ADDI | RD(TMP_REG3) | RS1(TMP_REG3) | IMM_I(high);469ins++;470}471472ins[1] = LUI | RD(reg) | (sljit_ins)((sljit_sw)addr & ~0xfff);473ins[2] = SLLI | RD(TMP_REG3) | RS1(TMP_REG3) | IMM_I((flags & PATCH_ABS52) ? 20 : 32);474ins[3] = XOR | RD(reg) | RS1(reg) | RS2(TMP_REG3);475ins += 3;476}477#endif /* !SLJIT_CONFIG_RISCV_32 */478479if (!(flags & JUMP_MOV_ADDR)) {480SLJIT_ASSERT((ins[1] & 0x707f) == JALR);481ins[1] = (ins[1] & 0xfffff) | IMM_I(addr);482} else483ins[1] = ADDI | RD(reg) | RS1(reg) | IMM_I(addr);484}485486static void reduce_code_size(struct sljit_compiler *compiler)487{488struct sljit_label *label;489struct sljit_jump *jump;490struct sljit_const *const_;491SLJIT_NEXT_DEFINE_TYPES;492sljit_uw total_size;493sljit_uw size_reduce = 0;494sljit_sw diff;495496label = compiler->labels;497jump = compiler->jumps;498const_ = compiler->consts;499SLJIT_NEXT_INIT_TYPES();500501while (1) {502SLJIT_GET_NEXT_MIN();503504if (next_min_addr == SLJIT_MAX_ADDRESS)505break;506507if (next_min_addr == next_label_size) {508label->size -= size_reduce;509510label = label->next;511next_label_size = SLJIT_GET_NEXT_SIZE(label);512}513514if (next_min_addr == next_const_addr) {515const_->addr -= size_reduce;516const_ = const_->next;517next_const_addr = SLJIT_GET_NEXT_ADDRESS(const_);518continue;519}520521if (next_min_addr != next_jump_addr)522continue;523524jump->addr -= size_reduce;525if (!(jump->flags & JUMP_MOV_ADDR)) {526total_size = JUMP_MAX_SIZE;527528if (!(jump->flags & SLJIT_REWRITABLE_JUMP)) {529if (jump->flags & JUMP_ADDR) {530#if (defined SLJIT_CONFIG_RISCV_64 && SLJIT_CONFIG_RISCV_64)531if (jump->u.target <= S32_MAX)532total_size = 2;533else if (jump->u.target <= S44_MAX)534total_size = 4;535else if (jump->u.target <= S52_MAX)536total_size = 5;537#endif /* SLJIT_CONFIG_RISCV_64 */538} else {539/* Unit size: instruction. */540diff = (sljit_sw)jump->u.label->size - (sljit_sw)jump->addr;541if (jump->u.label->size > jump->addr) {542SLJIT_ASSERT(jump->u.label->size - size_reduce >= jump->addr);543diff -= (sljit_sw)size_reduce;544}545546if ((jump->flags & IS_COND) && (diff + 1) <= (BRANCH_MAX / SSIZE_OF(ins)) && (diff + 1) >= (BRANCH_MIN / SSIZE_OF(ins)))547total_size = 0;548else if (diff >= (JUMP_MIN / SSIZE_OF(ins)) && diff <= (JUMP_MAX / SSIZE_OF(ins)))549total_size = 1;550#if (defined SLJIT_CONFIG_RISCV_64 && SLJIT_CONFIG_RISCV_64)551else if (diff >= (S32_MIN / SSIZE_OF(ins)) && diff <= (S32_MAX / SSIZE_OF(ins)))552total_size = 2;553#endif /* SLJIT_CONFIG_RISCV_64 */554}555}556557size_reduce += JUMP_MAX_SIZE - total_size;558jump->flags |= total_size << JUMP_SIZE_SHIFT;559#if (defined SLJIT_CONFIG_RISCV_64 && SLJIT_CONFIG_RISCV_64)560} else {561total_size = 5;562563if (!(jump->flags & JUMP_ADDR)) {564/* Real size minus 1. Unit size: instruction. */565diff = (sljit_sw)jump->u.label->size - (sljit_sw)jump->addr;566if (jump->u.label->size > jump->addr) {567SLJIT_ASSERT(jump->u.label->size - size_reduce >= jump->addr);568diff -= (sljit_sw)size_reduce;569}570571if (diff >= (S32_MIN / SSIZE_OF(ins)) && diff <= (S32_MAX / SSIZE_OF(ins)))572total_size = 1;573} else if (jump->u.target < S32_MAX)574total_size = 1;575else if (jump->u.target < S44_MAX)576total_size = 3;577else if (jump->u.target <= S52_MAX)578total_size = 4;579580size_reduce += 5 - total_size;581jump->flags |= total_size << JUMP_SIZE_SHIFT;582#endif /* !SLJIT_CONFIG_RISCV_64 */583}584585jump = jump->next;586next_jump_addr = SLJIT_GET_NEXT_ADDRESS(jump);587}588589compiler->size -= size_reduce;590}591592SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compiler, sljit_s32 options, void *exec_allocator_data)593{594struct sljit_memory_fragment *buf;595sljit_ins *code;596sljit_ins *code_ptr;597sljit_ins *buf_ptr;598sljit_ins *buf_end;599sljit_uw word_count;600SLJIT_NEXT_DEFINE_TYPES;601sljit_sw executable_offset;602sljit_uw addr;603604struct sljit_label *label;605struct sljit_jump *jump;606struct sljit_const *const_;607608CHECK_ERROR_PTR();609CHECK_PTR(check_sljit_generate_code(compiler));610611reduce_code_size(compiler);612613code = (sljit_ins*)allocate_executable_memory(compiler->size * sizeof(sljit_ins), options, exec_allocator_data, &executable_offset);614PTR_FAIL_WITH_EXEC_IF(code);615616reverse_buf(compiler);617buf = compiler->buf;618619code_ptr = code;620word_count = 0;621label = compiler->labels;622jump = compiler->jumps;623const_ = compiler->consts;624SLJIT_NEXT_INIT_TYPES();625SLJIT_GET_NEXT_MIN();626627do {628buf_ptr = (sljit_ins*)buf->memory;629buf_end = buf_ptr + (buf->used_size >> 2);630do {631*code_ptr = *buf_ptr++;632if (next_min_addr == word_count) {633SLJIT_ASSERT(!label || label->size >= word_count);634SLJIT_ASSERT(!jump || jump->addr >= word_count);635SLJIT_ASSERT(!const_ || const_->addr >= word_count);636637/* These structures are ordered by their address. */638if (next_min_addr == next_label_size) {639label->u.addr = (sljit_uw)SLJIT_ADD_EXEC_OFFSET(code_ptr, executable_offset);640label->size = (sljit_uw)(code_ptr - code);641label = label->next;642next_label_size = SLJIT_GET_NEXT_SIZE(label);643}644645if (next_min_addr == next_jump_addr) {646if (!(jump->flags & JUMP_MOV_ADDR)) {647word_count = word_count - 1 + (jump->flags >> JUMP_SIZE_SHIFT);648code_ptr = detect_jump_type(jump, code_ptr, code, executable_offset);649SLJIT_ASSERT((jump->flags & PATCH_B) || ((sljit_uw)code_ptr - jump->addr < (jump->flags >> JUMP_SIZE_SHIFT) * sizeof(sljit_ins)));650} else {651#if (defined SLJIT_CONFIG_RISCV_32 && SLJIT_CONFIG_RISCV_32)652word_count += 1;653jump->addr = (sljit_uw)code_ptr;654code_ptr += 1;655#else /* !SLJIT_CONFIG_RISCV_32 */656word_count += jump->flags >> JUMP_SIZE_SHIFT;657addr = (sljit_uw)code_ptr;658code_ptr += mov_addr_get_length(jump, code_ptr, code, executable_offset);659jump->addr = addr;660#endif /* SLJIT_CONFIG_RISCV_32 */661}662jump = jump->next;663next_jump_addr = SLJIT_GET_NEXT_ADDRESS(jump);664} else if (next_min_addr == next_const_addr) {665const_->addr = (sljit_uw)code_ptr;666const_ = const_->next;667next_const_addr = SLJIT_GET_NEXT_ADDRESS(const_);668}669670SLJIT_GET_NEXT_MIN();671}672code_ptr++;673word_count++;674} while (buf_ptr < buf_end);675676buf = buf->next;677} while (buf);678679if (label && label->size == word_count) {680label->u.addr = (sljit_uw)code_ptr;681label->size = (sljit_uw)(code_ptr - code);682label = label->next;683}684685SLJIT_ASSERT(!label);686SLJIT_ASSERT(!jump);687SLJIT_ASSERT(!const_);688SLJIT_ASSERT(code_ptr - code <= (sljit_sw)compiler->size);689690jump = compiler->jumps;691while (jump) {692do {693if (!(jump->flags & (PATCH_B | PATCH_J)) || (jump->flags & JUMP_MOV_ADDR)) {694load_addr_to_reg(jump, executable_offset);695break;696}697698addr = (jump->flags & JUMP_ADDR) ? jump->u.target : jump->u.label->u.addr;699buf_ptr = (sljit_ins *)jump->addr;700addr -= (sljit_uw)SLJIT_ADD_EXEC_OFFSET(buf_ptr, executable_offset);701702if (jump->flags & PATCH_B) {703SLJIT_ASSERT((sljit_sw)addr >= BRANCH_MIN && (sljit_sw)addr <= BRANCH_MAX);704addr = ((addr & 0x800) >> 4) | ((addr & 0x1e) << 7) | ((addr & 0x7e0) << 20) | ((addr & 0x1000) << 19);705buf_ptr[0] |= (sljit_ins)addr;706break;707}708709SLJIT_ASSERT((sljit_sw)addr >= JUMP_MIN && (sljit_sw)addr <= JUMP_MAX);710addr = (addr & 0xff000) | ((addr & 0x800) << 9) | ((addr & 0x7fe) << 20) | ((addr & 0x100000) << 11);711buf_ptr[0] = JAL | RD((jump->flags & IS_CALL) ? RETURN_ADDR_REG : TMP_ZERO) | (sljit_ins)addr;712} while (0);713714jump = jump->next;715}716717compiler->error = SLJIT_ERR_COMPILED;718compiler->executable_offset = executable_offset;719compiler->executable_size = (sljit_uw)(code_ptr - code) * sizeof(sljit_ins);720721code = (sljit_ins *)SLJIT_ADD_EXEC_OFFSET(code, executable_offset);722code_ptr = (sljit_ins *)SLJIT_ADD_EXEC_OFFSET(code_ptr, executable_offset);723724SLJIT_CACHE_FLUSH(code, code_ptr);725SLJIT_UPDATE_WX_FLAGS(code, code_ptr, 1);726return code;727}728729SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_has_cpu_feature(sljit_s32 feature_type)730{731switch (feature_type) {732case SLJIT_HAS_FPU:733#ifdef SLJIT_IS_FPU_AVAILABLE734return (SLJIT_IS_FPU_AVAILABLE) != 0;735#elif defined(__riscv_float_abi_soft)736return 0;737#else /* !SLJIT_IS_FPU_AVAILABLE && !__riscv_float_abi_soft */738return 1;739#endif /* SLJIT_IS_FPU_AVAILABLE */740case SLJIT_HAS_ZERO_REGISTER:741case SLJIT_HAS_COPY_F32:742#if (defined SLJIT_CONFIG_RISCV_64 && SLJIT_CONFIG_RISCV_64)743case SLJIT_HAS_COPY_F64:744#endif /* !SLJIT_CONFIG_RISCV_64 */745case SLJIT_HAS_ATOMIC:746case SLJIT_HAS_MEMORY_BARRIER:747#ifdef __riscv_vector748case SLJIT_HAS_SIMD:749#endif /* __riscv_vector */750return 1;751#ifdef __riscv_zbb752case SLJIT_HAS_CLZ:753case SLJIT_HAS_CTZ:754case SLJIT_HAS_REV:755case SLJIT_HAS_ROT:756return 1;757#endif /* __riscv_zbb */758default:759return 0;760}761}762763SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_cmp_info(sljit_s32 type)764{765switch (type) {766case SLJIT_UNORDERED_OR_EQUAL:767case SLJIT_ORDERED_NOT_EQUAL:768return 2;769770case SLJIT_UNORDERED:771case SLJIT_ORDERED:772return 1;773}774775return 0;776}777778/* --------------------------------------------------------------------- */779/* Entry, exit */780/* --------------------------------------------------------------------- */781782/* Creates an index in data_transfer_insts array. */783#define LOAD_DATA 0x01784#define WORD_DATA 0x00785#define BYTE_DATA 0x02786#define HALF_DATA 0x04787#define INT_DATA 0x06788#define SIGNED_DATA 0x08789/* Separates integer and floating point registers */790#define GPR_REG 0x0f791#define DOUBLE_DATA 0x10792#define SINGLE_DATA 0x12793794#define MEM_MASK 0x1f795796#define ARG_TEST 0x00020797#define ALT_KEEP_CACHE 0x00040798#define CUMULATIVE_OP 0x00080799#define IMM_OP 0x00100800#define MOVE_OP 0x00200801#define SRC2_IMM 0x00400802803#define UNUSED_DEST 0x00800804#define REG_DEST 0x01000805#define REG1_SOURCE 0x02000806#define REG2_SOURCE 0x04000807#define SLOW_SRC1 0x08000808#define SLOW_SRC2 0x10000809#define SLOW_DEST 0x20000810#define MEM_USE_TMP2 0x40000811812#if (defined SLJIT_CONFIG_RISCV_32 && SLJIT_CONFIG_RISCV_32)813#define STACK_STORE SW814#define STACK_LOAD LW815#else /* !SLJIT_CONFIG_RISCV_32 */816#define STACK_STORE SD817#define STACK_LOAD LD818#endif /* SLJIT_CONFIG_RISCV_32 */819820#if (defined SLJIT_CONFIG_RISCV_32 && SLJIT_CONFIG_RISCV_32)821#include "sljitNativeRISCV_32.c"822#else /* !SLJIT_CONFIG_RISCV_32 */823#include "sljitNativeRISCV_64.c"824#endif /* SLJIT_CONFIG_RISCV_32 */825826#define STACK_MAX_DISTANCE (-SIMM_MIN)827828static sljit_s32 emit_op_mem(struct sljit_compiler *compiler, sljit_s32 flags, sljit_s32 reg, sljit_s32 arg, sljit_sw argw);829830SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_enter(struct sljit_compiler *compiler,831sljit_s32 options, sljit_s32 arg_types,832sljit_s32 scratches, sljit_s32 saveds, sljit_s32 local_size)833{834sljit_s32 fscratches = ENTER_GET_FLOAT_REGS(scratches);835sljit_s32 fsaveds = ENTER_GET_FLOAT_REGS(saveds);836sljit_s32 i, tmp, offset;837sljit_s32 saved_arg_count = SLJIT_KEPT_SAVEDS_COUNT(options);838839CHECK_ERROR();840CHECK(check_sljit_emit_enter(compiler, options, arg_types, scratches, saveds, local_size));841set_emit_enter(compiler, options, arg_types, scratches, saveds, local_size);842843scratches = ENTER_GET_REGS(scratches);844saveds = ENTER_GET_REGS(saveds);845local_size += GET_SAVED_REGISTERS_SIZE(scratches, saveds - saved_arg_count, 1);846#if (defined SLJIT_CONFIG_RISCV_32 && SLJIT_CONFIG_RISCV_32)847if (fsaveds > 0 || fscratches >= SLJIT_FIRST_SAVED_FLOAT_REG) {848if ((local_size & SSIZE_OF(sw)) != 0)849local_size += SSIZE_OF(sw);850local_size += GET_SAVED_FLOAT_REGISTERS_SIZE(fscratches, fsaveds, f64);851}852#else /* !SLJIT_CONFIG_RISCV_32 */853local_size += GET_SAVED_FLOAT_REGISTERS_SIZE(fscratches, fsaveds, f64);854#endif /* SLJIT_CONFIG_RISCV_32 */855local_size = (local_size + SLJIT_LOCALS_OFFSET + 15) & ~0xf;856compiler->local_size = local_size;857858if (local_size <= STACK_MAX_DISTANCE) {859/* Frequent case. */860FAIL_IF(push_inst(compiler, ADDI | RD(SLJIT_SP) | RS1(SLJIT_SP) | IMM_I(-local_size)));861offset = local_size - SSIZE_OF(sw);862local_size = 0;863} else {864FAIL_IF(push_inst(compiler, ADDI | RD(SLJIT_SP) | RS1(SLJIT_SP) | IMM_I(STACK_MAX_DISTANCE)));865local_size -= STACK_MAX_DISTANCE;866867if (local_size > STACK_MAX_DISTANCE)868FAIL_IF(load_immediate(compiler, TMP_REG1, local_size, TMP_REG3));869offset = STACK_MAX_DISTANCE - SSIZE_OF(sw);870}871872FAIL_IF(push_imm_s_inst(compiler, STACK_STORE | RS1(SLJIT_SP) | RS2(RETURN_ADDR_REG), offset));873874tmp = SLJIT_S0 - saveds;875for (i = SLJIT_S0 - saved_arg_count; i > tmp; i--) {876offset -= SSIZE_OF(sw);877FAIL_IF(push_imm_s_inst(compiler, STACK_STORE | RS1(SLJIT_SP) | RS2(i), offset));878}879880for (i = scratches; i >= SLJIT_FIRST_SAVED_REG; i--) {881offset -= SSIZE_OF(sw);882FAIL_IF(push_imm_s_inst(compiler, STACK_STORE | RS1(SLJIT_SP) | RS2(i), offset));883}884885#if (defined SLJIT_CONFIG_RISCV_32 && SLJIT_CONFIG_RISCV_32)886/* This alignment is valid because offset is not used after storing FPU regs. */887if ((offset & SSIZE_OF(sw)) != 0)888offset -= SSIZE_OF(sw);889#endif /* SLJIT_CONFIG_RISCV_32 */890891tmp = SLJIT_FS0 - fsaveds;892for (i = SLJIT_FS0; i > tmp; i--) {893offset -= SSIZE_OF(f64);894FAIL_IF(push_imm_s_inst(compiler, FSD | RS1(SLJIT_SP) | FRS2(i), offset));895}896897for (i = fscratches; i >= SLJIT_FIRST_SAVED_FLOAT_REG; i--) {898offset -= SSIZE_OF(f64);899FAIL_IF(push_imm_s_inst(compiler, FSD | RS1(SLJIT_SP) | FRS2(i), offset));900}901902if (local_size > STACK_MAX_DISTANCE)903FAIL_IF(push_inst(compiler, SUB | RD(SLJIT_SP) | RS1(SLJIT_SP) | RS2(TMP_REG1)));904else if (local_size > 0)905FAIL_IF(push_inst(compiler, ADDI | RD(SLJIT_SP) | RS1(SLJIT_SP) | IMM_I(-local_size)));906907if (options & SLJIT_ENTER_REG_ARG)908return SLJIT_SUCCESS;909910arg_types >>= SLJIT_ARG_SHIFT;911saved_arg_count = 0;912tmp = SLJIT_R0;913914while (arg_types > 0) {915if ((arg_types & SLJIT_ARG_MASK) < SLJIT_ARG_TYPE_F64) {916if (!(arg_types & SLJIT_ARG_TYPE_SCRATCH_REG)) {917FAIL_IF(push_inst(compiler, ADDI | RD(SLJIT_S0 - saved_arg_count) | RS1(tmp) | IMM_I(0)));918saved_arg_count++;919}920tmp++;921}922923arg_types >>= SLJIT_ARG_SHIFT;924}925926return SLJIT_SUCCESS;927}928929#undef STACK_MAX_DISTANCE930931SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_set_context(struct sljit_compiler *compiler,932sljit_s32 options, sljit_s32 arg_types,933sljit_s32 scratches, sljit_s32 saveds, sljit_s32 local_size)934{935sljit_s32 fscratches = ENTER_GET_FLOAT_REGS(scratches);936sljit_s32 fsaveds = ENTER_GET_FLOAT_REGS(saveds);937938CHECK_ERROR();939CHECK(check_sljit_set_context(compiler, options, arg_types, scratches, saveds, local_size));940set_emit_enter(compiler, options, arg_types, scratches, saveds, local_size);941942scratches = ENTER_GET_REGS(scratches);943saveds = ENTER_GET_REGS(saveds);944local_size += GET_SAVED_REGISTERS_SIZE(scratches, saveds - SLJIT_KEPT_SAVEDS_COUNT(options), 1);945#if (defined SLJIT_CONFIG_RISCV_32 && SLJIT_CONFIG_RISCV_32)946if (fsaveds > 0 || fscratches >= SLJIT_FIRST_SAVED_FLOAT_REG) {947if ((local_size & SSIZE_OF(sw)) != 0)948local_size += SSIZE_OF(sw);949local_size += GET_SAVED_FLOAT_REGISTERS_SIZE(fscratches, fsaveds, f64);950}951#else /* !SLJIT_CONFIG_RISCV_32 */952local_size += GET_SAVED_FLOAT_REGISTERS_SIZE(fscratches, fsaveds, f64);953#endif /* SLJIT_CONFIG_RISCV_32 */954compiler->local_size = (local_size + SLJIT_LOCALS_OFFSET + 15) & ~0xf;955956return SLJIT_SUCCESS;957}958959#define STACK_MAX_DISTANCE (-SIMM_MIN - 16)960961static sljit_s32 emit_stack_frame_release(struct sljit_compiler *compiler, sljit_s32 is_return_to)962{963sljit_s32 i, tmp, offset;964sljit_s32 local_size = compiler->local_size;965966if (local_size > STACK_MAX_DISTANCE) {967local_size -= STACK_MAX_DISTANCE;968969if (local_size > STACK_MAX_DISTANCE) {970FAIL_IF(load_immediate(compiler, TMP_REG2, local_size, TMP_REG3));971FAIL_IF(push_inst(compiler, ADD | RD(SLJIT_SP) | RS1(SLJIT_SP) | RS2(TMP_REG2)));972} else973FAIL_IF(push_inst(compiler, ADDI | RD(SLJIT_SP) | RS1(SLJIT_SP) | IMM_I(local_size)));974975local_size = STACK_MAX_DISTANCE;976}977978SLJIT_ASSERT(local_size > 0);979980offset = local_size - SSIZE_OF(sw);981if (!is_return_to)982FAIL_IF(push_inst(compiler, STACK_LOAD | RD(RETURN_ADDR_REG) | RS1(SLJIT_SP) | IMM_I(offset)));983984tmp = SLJIT_S0 - compiler->saveds;985for (i = SLJIT_S0 - SLJIT_KEPT_SAVEDS_COUNT(compiler->options); i > tmp; i--) {986offset -= SSIZE_OF(sw);987FAIL_IF(push_inst(compiler, STACK_LOAD | RD(i) | RS1(SLJIT_SP) | IMM_I(offset)));988}989990for (i = compiler->scratches; i >= SLJIT_FIRST_SAVED_REG; i--) {991offset -= SSIZE_OF(sw);992FAIL_IF(push_inst(compiler, STACK_LOAD | RD(i) | RS1(SLJIT_SP) | IMM_I(offset)));993}994995#if (defined SLJIT_CONFIG_RISCV_32 && SLJIT_CONFIG_RISCV_32)996/* This alignment is valid because offset is not used after storing FPU regs. */997if ((offset & SSIZE_OF(sw)) != 0)998offset -= SSIZE_OF(sw);999#endif /* SLJIT_CONFIG_RISCV_32 */10001001tmp = SLJIT_FS0 - compiler->fsaveds;1002for (i = SLJIT_FS0; i > tmp; i--) {1003offset -= SSIZE_OF(f64);1004FAIL_IF(push_inst(compiler, FLD | FRD(i) | RS1(SLJIT_SP) | IMM_I(offset)));1005}10061007for (i = compiler->fscratches; i >= SLJIT_FIRST_SAVED_FLOAT_REG; i--) {1008offset -= SSIZE_OF(f64);1009FAIL_IF(push_inst(compiler, FLD | FRD(i) | RS1(SLJIT_SP) | IMM_I(offset)));1010}10111012return push_inst(compiler, ADDI | RD(SLJIT_SP) | RS1(SLJIT_SP) | IMM_I(local_size));1013}10141015#undef STACK_MAX_DISTANCE10161017SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_return_void(struct sljit_compiler *compiler)1018{1019CHECK_ERROR();1020CHECK(check_sljit_emit_return_void(compiler));10211022FAIL_IF(emit_stack_frame_release(compiler, 0));1023return push_inst(compiler, JALR | RD(TMP_ZERO) | RS1(RETURN_ADDR_REG) | IMM_I(0));1024}10251026SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_return_to(struct sljit_compiler *compiler,1027sljit_s32 src, sljit_sw srcw)1028{1029CHECK_ERROR();1030CHECK(check_sljit_emit_return_to(compiler, src, srcw));10311032if (src & SLJIT_MEM) {1033ADJUST_LOCAL_OFFSET(src, srcw);1034FAIL_IF(emit_op_mem(compiler, WORD_DATA | LOAD_DATA, TMP_REG1, src, srcw));1035src = TMP_REG1;1036srcw = 0;1037} else if (src >= SLJIT_FIRST_SAVED_REG && src <= (SLJIT_S0 - SLJIT_KEPT_SAVEDS_COUNT(compiler->options))) {1038FAIL_IF(push_inst(compiler, ADDI | RD(TMP_REG1) | RS1(src) | IMM_I(0)));1039src = TMP_REG1;1040srcw = 0;1041}10421043FAIL_IF(emit_stack_frame_release(compiler, 1));10441045SLJIT_SKIP_CHECKS(compiler);1046return sljit_emit_ijump(compiler, SLJIT_JUMP, src, srcw);1047}10481049/* --------------------------------------------------------------------- */1050/* Operators */1051/* --------------------------------------------------------------------- */10521053#if (defined SLJIT_CONFIG_RISCV_32 && SLJIT_CONFIG_RISCV_32)1054#define ARCH_32_64(a, b) a1055#else /* !SLJIT_CONFIG_RISCV_32 */1056#define ARCH_32_64(a, b) b1057#endif /* SLJIT_CONFIG_RISCV_32 */10581059static const sljit_ins data_transfer_insts[16 + 4] = {1060/* u w s */ ARCH_32_64(F3(0x2) | OPC(0x23) /* sw */, F3(0x3) | OPC(0x23) /* sd */),1061/* u w l */ ARCH_32_64(F3(0x2) | OPC(0x3) /* lw */, F3(0x3) | OPC(0x3) /* ld */),1062/* u b s */ F3(0x0) | OPC(0x23) /* sb */,1063/* u b l */ F3(0x4) | OPC(0x3) /* lbu */,1064/* u h s */ F3(0x1) | OPC(0x23) /* sh */,1065/* u h l */ F3(0x5) | OPC(0x3) /* lhu */,1066/* u i s */ F3(0x2) | OPC(0x23) /* sw */,1067/* u i l */ ARCH_32_64(F3(0x2) | OPC(0x3) /* lw */, F3(0x6) | OPC(0x3) /* lwu */),10681069/* s w s */ ARCH_32_64(F3(0x2) | OPC(0x23) /* sw */, F3(0x3) | OPC(0x23) /* sd */),1070/* s w l */ ARCH_32_64(F3(0x2) | OPC(0x3) /* lw */, F3(0x3) | OPC(0x3) /* ld */),1071/* s b s */ F3(0x0) | OPC(0x23) /* sb */,1072/* s b l */ F3(0x0) | OPC(0x3) /* lb */,1073/* s h s */ F3(0x1) | OPC(0x23) /* sh */,1074/* s h l */ F3(0x1) | OPC(0x3) /* lh */,1075/* s i s */ F3(0x2) | OPC(0x23) /* sw */,1076/* s i l */ F3(0x2) | OPC(0x3) /* lw */,10771078/* d s */ F3(0x3) | OPC(0x27) /* fsd */,1079/* d l */ F3(0x3) | OPC(0x7) /* fld */,1080/* s s */ F3(0x2) | OPC(0x27) /* fsw */,1081/* s l */ F3(0x2) | OPC(0x7) /* flw */,1082};10831084#undef ARCH_32_6410851086static sljit_s32 push_mem_inst(struct sljit_compiler *compiler, sljit_s32 flags, sljit_s32 reg, sljit_s32 base, sljit_sw offset)1087{1088sljit_ins ins;10891090SLJIT_ASSERT(FAST_IS_REG(base) && offset <= 0xfff && offset >= SIMM_MIN);10911092ins = data_transfer_insts[flags & MEM_MASK] | RS1(base);1093if (flags & LOAD_DATA)1094ins |= ((flags & MEM_MASK) <= GPR_REG ? RD(reg) : FRD(reg)) | IMM_I(offset);1095else1096ins |= ((flags & MEM_MASK) <= GPR_REG ? RS2(reg) : FRS2(reg)) | IMM_S(offset);10971098return push_inst(compiler, ins);1099}11001101/* Can perform an operation using at most 1 instruction. */1102static sljit_s32 getput_arg_fast(struct sljit_compiler *compiler, sljit_s32 flags, sljit_s32 reg, sljit_s32 arg, sljit_sw argw)1103{1104SLJIT_ASSERT(arg & SLJIT_MEM);11051106if (!(arg & OFFS_REG_MASK) && argw <= SIMM_MAX && argw >= SIMM_MIN) {1107/* Works for both absoulte and relative addresses. */1108if (SLJIT_UNLIKELY(flags & ARG_TEST))1109return 1;11101111FAIL_IF(push_mem_inst(compiler, flags, reg, arg & REG_MASK, argw));1112return -1;1113}1114return 0;1115}11161117#define TO_ARGW_HI(argw) (((argw) & ~0xfff) + (((argw) & 0x800) ? 0x1000 : 0))11181119/* See getput_arg below.1120Note: can_cache is called only for binary operators. */1121static sljit_s32 can_cache(sljit_s32 arg, sljit_sw argw, sljit_s32 next_arg, sljit_sw next_argw)1122{1123SLJIT_ASSERT((arg & SLJIT_MEM) && (next_arg & SLJIT_MEM));11241125/* Simple operation except for updates. */1126if (arg & OFFS_REG_MASK) {1127argw &= 0x3;1128next_argw &= 0x3;1129if (argw && argw == next_argw && (arg == next_arg || (arg & OFFS_REG_MASK) == (next_arg & OFFS_REG_MASK)))1130return 1;1131return 0;1132}11331134if (arg == next_arg) {1135if (((next_argw - argw) <= SIMM_MAX && (next_argw - argw) >= SIMM_MIN)1136|| TO_ARGW_HI(argw) == TO_ARGW_HI(next_argw))1137return 1;1138return 0;1139}11401141return 0;1142}11431144/* Emit the necessary instructions. See can_cache above. */1145static 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)1146{1147sljit_s32 base = arg & REG_MASK;1148sljit_s32 tmp_r = (flags & MEM_USE_TMP2) ? TMP_REG2 : TMP_REG1;1149sljit_sw offset, argw_hi;1150#if defined __riscv_zba1151sljit_ins ins = ADD;1152#endif /* __riscv_zba */11531154SLJIT_ASSERT(arg & SLJIT_MEM);1155if (!(next_arg & SLJIT_MEM)) {1156next_arg = 0;1157next_argw = 0;1158}11591160if (SLJIT_UNLIKELY(arg & OFFS_REG_MASK)) {1161argw &= 0x3;11621163#if defined __riscv_zba1164switch (argw) {1165case 1:1166ins = SH1ADD;1167break;1168case 2:1169ins = SH2ADD;1170break;1171case 3:1172ins = SH3ADD;1173break;1174}1175FAIL_IF(push_inst(compiler, ins | RD(tmp_r) | RS1(OFFS_REG(arg)) | RS2(base)));1176#else /* !__riscv_zba */1177/* Using the cache. */1178if (argw == compiler->cache_argw) {1179if (arg == compiler->cache_arg)1180return push_mem_inst(compiler, flags, reg, TMP_REG3, 0);11811182if ((SLJIT_MEM | (arg & OFFS_REG_MASK)) == compiler->cache_arg) {1183if (arg == next_arg && argw == (next_argw & 0x3)) {1184compiler->cache_arg = arg;1185compiler->cache_argw = argw;1186FAIL_IF(push_inst(compiler, ADD | RD(TMP_REG3) | RS1(TMP_REG3) | RS2(base)));1187return push_mem_inst(compiler, flags, reg, TMP_REG3, 0);1188}1189FAIL_IF(push_inst(compiler, ADD | RD(tmp_r) | RS1(base) | RS2(TMP_REG3)));1190return push_mem_inst(compiler, flags, reg, tmp_r, 0);1191}1192}11931194if (SLJIT_UNLIKELY(argw)) {1195compiler->cache_arg = SLJIT_MEM | (arg & OFFS_REG_MASK);1196compiler->cache_argw = argw;1197FAIL_IF(push_inst(compiler, SLLI | RD(TMP_REG3) | RS1(OFFS_REG(arg)) | IMM_I(argw)));1198}11991200if (arg == next_arg && argw == (next_argw & 0x3)) {1201compiler->cache_arg = arg;1202compiler->cache_argw = argw;1203FAIL_IF(push_inst(compiler, ADD | RD(TMP_REG3) | RS1(base) | RS2(!argw ? OFFS_REG(arg) : TMP_REG3)));1204tmp_r = TMP_REG3;1205}1206else1207FAIL_IF(push_inst(compiler, ADD | RD(tmp_r) | RS1(base) | RS2(!argw ? OFFS_REG(arg) : TMP_REG3)));1208#endif /* __riscv_zba */12091210return push_mem_inst(compiler, flags, reg, tmp_r, 0);1211}12121213if (compiler->cache_arg == arg && argw - compiler->cache_argw <= SIMM_MAX && argw - compiler->cache_argw >= SIMM_MIN)1214return push_mem_inst(compiler, flags, reg, TMP_REG3, argw - compiler->cache_argw);12151216if (compiler->cache_arg == SLJIT_MEM && (argw - compiler->cache_argw <= SIMM_MAX) && (argw - compiler->cache_argw >= SIMM_MIN)) {1217offset = argw - compiler->cache_argw;1218} else {1219compiler->cache_arg = SLJIT_MEM;12201221argw_hi = TO_ARGW_HI(argw);12221223if (next_arg && next_argw - argw <= SIMM_MAX && next_argw - argw >= SIMM_MIN && argw_hi != TO_ARGW_HI(next_argw)) {1224FAIL_IF(load_immediate(compiler, TMP_REG3, argw, tmp_r));1225compiler->cache_argw = argw;1226offset = 0;1227} else {1228FAIL_IF(load_immediate(compiler, TMP_REG3, argw_hi, tmp_r));1229compiler->cache_argw = argw_hi;1230offset = argw & 0xfff;1231argw = argw_hi;1232}1233}12341235if (!base)1236return push_mem_inst(compiler, flags, reg, TMP_REG3, offset);12371238if (arg == next_arg && next_argw - argw <= SIMM_MAX && next_argw - argw >= SIMM_MIN) {1239compiler->cache_arg = arg;1240FAIL_IF(push_inst(compiler, ADD | RD(TMP_REG3) | RS1(TMP_REG3) | RS2(base)));1241return push_mem_inst(compiler, flags, reg, TMP_REG3, offset);1242}12431244FAIL_IF(push_inst(compiler, ADD | RD(tmp_r) | RS1(TMP_REG3) | RS2(base)));1245return push_mem_inst(compiler, flags, reg, tmp_r, offset);1246}12471248static sljit_s32 emit_op_mem(struct sljit_compiler *compiler, sljit_s32 flags, sljit_s32 reg, sljit_s32 arg, sljit_sw argw)1249{1250sljit_s32 base = arg & REG_MASK;1251sljit_s32 tmp_r = TMP_REG1;12521253if (getput_arg_fast(compiler, flags, reg, arg, argw))1254return compiler->error;12551256if ((flags & MEM_MASK) <= GPR_REG && (flags & LOAD_DATA))1257tmp_r = reg;12581259if (SLJIT_UNLIKELY(arg & OFFS_REG_MASK)) {1260argw &= 0x3;12611262if (SLJIT_UNLIKELY(argw)) {1263FAIL_IF(push_inst(compiler, SLLI | RD(tmp_r) | RS1(OFFS_REG(arg)) | IMM_I(argw)));1264FAIL_IF(push_inst(compiler, ADD | RD(tmp_r) | RS1(tmp_r) | RS2(base)));1265}1266else1267FAIL_IF(push_inst(compiler, ADD | RD(tmp_r) | RS1(base) | RS2(OFFS_REG(arg))));12681269argw = 0;1270} else {1271FAIL_IF(load_immediate(compiler, tmp_r, TO_ARGW_HI(argw), TMP_REG3));12721273if (base != 0)1274FAIL_IF(push_inst(compiler, ADD | RD(tmp_r) | RS1(tmp_r) | RS2(base)));1275}12761277return push_mem_inst(compiler, flags, reg, tmp_r, argw & 0xfff);1278}12791280static 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)1281{1282if (getput_arg_fast(compiler, flags, reg, arg1, arg1w))1283return compiler->error;1284return getput_arg(compiler, flags, reg, arg1, arg1w, arg2, arg2w);1285}12861287#if (defined SLJIT_CONFIG_RISCV_32 && SLJIT_CONFIG_RISCV_32)1288#define WORD 01289#define WORD_32 01290#define IMM_EXTEND(v) (IMM_I(v))1291#else /* !SLJIT_CONFIG_RISCV_32 */1292#define WORD word1293#define WORD_32 0x081294#define IMM_EXTEND(v) (IMM_I((op & SLJIT_32) ? (v) : (32 + (v))))1295#endif /* SLJIT_CONFIG_RISCV_32 */1296#ifndef __riscv_zbb1297static sljit_s32 emit_clz_ctz(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 dst, sljit_sw src)1298{1299sljit_s32 is_clz = (GET_OPCODE(op) == SLJIT_CLZ);1300#if (defined SLJIT_CONFIG_RISCV_64 && SLJIT_CONFIG_RISCV_64)1301sljit_ins word = (sljit_ins)(op & SLJIT_32) >> 5;1302sljit_ins word_size = (op & SLJIT_32) ? 32 : 64;1303#else /* !SLJIT_CONFIG_RISCV_64 */1304sljit_ins word_size = 32;1305#endif /* SLJIT_CONFIG_RISCV_64 */13061307SLJIT_ASSERT(WORD == 0 || WORD == 0x8);13081309/* The OTHER_FLAG is the counter. */1310FAIL_IF(push_inst(compiler, ADDI | WORD | RD(OTHER_FLAG) | RS1(TMP_ZERO) | IMM_I(word_size)));13111312/* The TMP_REG2 is the next value. */1313if (src != TMP_REG2)1314FAIL_IF(push_inst(compiler, ADDI | WORD | RD(TMP_REG2) | RS1(src) | IMM_I(0)));13151316FAIL_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)));13171318FAIL_IF(push_inst(compiler, ADDI | WORD | RD(OTHER_FLAG) | RS1(TMP_ZERO) | IMM_I(0)));1319if (!is_clz) {1320FAIL_IF(push_inst(compiler, ANDI | RD(TMP_REG1) | RS1(TMP_REG2) | IMM_I(1)));1321FAIL_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)));1322} else1323FAIL_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)));13241325/* The TMP_REG1 is the next shift. */1326FAIL_IF(push_inst(compiler, ADDI | WORD | RD(TMP_REG1) | RS1(TMP_ZERO) | IMM_I(word_size)));13271328FAIL_IF(push_inst(compiler, ADDI | WORD | RD(EQUAL_FLAG) | RS1(TMP_REG2) | IMM_I(0)));1329FAIL_IF(push_inst(compiler, SRLI | WORD | RD(TMP_REG1) | RS1(TMP_REG1) | IMM_I(1)));13301331FAIL_IF(push_inst(compiler, (is_clz ? SRL : SLL) | WORD | RD(TMP_REG2) | RS1(EQUAL_FLAG) | RS2(TMP_REG1)));1332FAIL_IF(push_inst(compiler, BNE | RS1(TMP_REG2) | RS2(TMP_ZERO) | ((sljit_ins)0xfe000e80 - ((2 * SSIZE_OF(ins)) << 7))));1333FAIL_IF(push_inst(compiler, ADDI | WORD | RD(TMP_REG2) | RS1(TMP_REG1) | IMM_I(-1)));1334FAIL_IF(push_inst(compiler, (is_clz ? SRL : SLL) | WORD | RD(TMP_REG2) | RS1(EQUAL_FLAG) | RS2(TMP_REG2)));1335FAIL_IF(push_inst(compiler, OR | RD(OTHER_FLAG) | RS1(OTHER_FLAG) | RS2(TMP_REG1)));1336FAIL_IF(push_inst(compiler, BEQ | RS1(TMP_REG2) | RS2(TMP_ZERO) | ((sljit_ins)0xfe000e80 - ((5 * SSIZE_OF(ins)) << 7))));13371338return push_inst(compiler, ADDI | WORD | RD(dst) | RS1(OTHER_FLAG) | IMM_I(0));1339}13401341static sljit_s32 emit_rev(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 dst, sljit_sw src)1342{1343SLJIT_UNUSED_ARG(op);13441345#if (defined SLJIT_CONFIG_RISCV_64 && SLJIT_CONFIG_RISCV_64)1346if (!(op & SLJIT_32)) {1347FAIL_IF(push_inst(compiler, LUI | RD(OTHER_FLAG) | 0x10000));1348FAIL_IF(push_inst(compiler, SRLI | RD(TMP_REG1) | RS1(src) | IMM_I(32)));1349FAIL_IF(push_inst(compiler, ADDI | RD(OTHER_FLAG) | RS1(OTHER_FLAG) | IMM_I(0xfff)));1350FAIL_IF(push_inst(compiler, SLLI | RD(dst) | RS1(src) | IMM_I(32)));1351FAIL_IF(push_inst(compiler, SLLI | RD(EQUAL_FLAG) | RS1(OTHER_FLAG) | IMM_I(32)));1352FAIL_IF(push_inst(compiler, OR | RD(dst) | RS1(dst) | RS2(TMP_REG1)));1353FAIL_IF(push_inst(compiler, OR | RD(OTHER_FLAG) | RS1(OTHER_FLAG) | RS2(EQUAL_FLAG)));13541355FAIL_IF(push_inst(compiler, SRLI | RD(TMP_REG1) | RS1(dst) | IMM_I(16)));1356FAIL_IF(push_inst(compiler, AND | RD(dst) | RS1(dst) | RS2(OTHER_FLAG)));1357FAIL_IF(push_inst(compiler, AND | RD(TMP_REG1) | RS1(TMP_REG1) | RS2(OTHER_FLAG)));1358FAIL_IF(push_inst(compiler, SLLI | RD(EQUAL_FLAG) | RS1(OTHER_FLAG) | IMM_I(8)));1359FAIL_IF(push_inst(compiler, SLLI | RD(dst) | RS1(dst) | IMM_I(16)));1360FAIL_IF(push_inst(compiler, XOR | RD(OTHER_FLAG) | RS1(OTHER_FLAG) | RS2(EQUAL_FLAG)));1361FAIL_IF(push_inst(compiler, OR | RD(dst) | RS1(dst) | RS2(TMP_REG1)));13621363FAIL_IF(push_inst(compiler, SRLI | RD(TMP_REG1) | RS1(dst) | IMM_I(8)));1364FAIL_IF(push_inst(compiler, AND | RD(dst) | RS1(dst) | RS2(OTHER_FLAG)));1365FAIL_IF(push_inst(compiler, AND | RD(TMP_REG1) | RS1(TMP_REG1) | RS2(OTHER_FLAG)));1366FAIL_IF(push_inst(compiler, SLLI | RD(dst) | RS1(dst) | IMM_I(8)));1367return push_inst(compiler, OR | RD(dst) | RS1(dst) | RS2(TMP_REG1));1368}1369#endif /* SLJIT_CONFIG_RISCV_64 */13701371FAIL_IF(push_inst(compiler, SRLI | WORD_32 | RD(TMP_REG1) | RS1(src) | IMM_I(16)));1372FAIL_IF(push_inst(compiler, LUI | RD(OTHER_FLAG) | 0xff0000));1373FAIL_IF(push_inst(compiler, SLLI | WORD_32 | RD(dst) | RS1(src) | IMM_I(16)));1374FAIL_IF(push_inst(compiler, ORI | RD(OTHER_FLAG) | RS1(OTHER_FLAG) | IMM_I(0xff)));1375FAIL_IF(push_inst(compiler, OR | RD(dst) | RS1(dst) | RS2(TMP_REG1)));13761377FAIL_IF(push_inst(compiler, SRLI | WORD_32 | RD(TMP_REG1) | RS1(dst) | IMM_I(8)));1378FAIL_IF(push_inst(compiler, AND | RD(dst) | RS1(dst) | RS2(OTHER_FLAG)));1379FAIL_IF(push_inst(compiler, AND | RD(TMP_REG1) | RS1(TMP_REG1) | RS2(OTHER_FLAG)));1380FAIL_IF(push_inst(compiler, SLLI | WORD_32 | RD(dst) | RS1(dst) | IMM_I(8)));1381return push_inst(compiler, OR | RD(dst) | RS1(dst) | RS2(TMP_REG1));1382}13831384static sljit_s32 emit_rev16(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 dst, sljit_sw src)1385{1386#if (defined SLJIT_CONFIG_RISCV_64 && SLJIT_CONFIG_RISCV_64)1387sljit_ins word = (sljit_ins)(op & SLJIT_32) >> 5;1388sljit_ins word_size = (op & SLJIT_32) ? 32 : 64;1389#else /* !SLJIT_CONFIG_RISCV_64 */1390sljit_ins word_size = 32;1391#endif /* SLJIT_CONFIG_RISCV_64 */13921393FAIL_IF(push_inst(compiler, SRLI | WORD | RD(TMP_REG1) | RS1(src) | IMM_I(8)));1394FAIL_IF(push_inst(compiler, SLLI | WORD | RD(dst) | RS1(src) | IMM_I(word_size - 8)));1395FAIL_IF(push_inst(compiler, ANDI | RD(TMP_REG1) | RS1(TMP_REG1) | IMM_I(0xff)));1396FAIL_IF(push_inst(compiler, (GET_OPCODE(op) == SLJIT_REV_U16 ? SRLI : SRAI) | WORD | RD(dst) | RS1(dst) | IMM_I(word_size - 16)));1397return push_inst(compiler, OR | RD(dst) | RS1(dst) | RS2(TMP_REG1));1398}1399#endif /* !__riscv_zbb */14001401#define EMIT_LOGICAL(op_imm, op_reg) \1402if (flags & SRC2_IMM) { \1403if (op & SLJIT_SET_Z) \1404FAIL_IF(push_inst(compiler, op_imm | RD(EQUAL_FLAG) | RS1(src1) | IMM_I(src2))); \1405if (!(flags & UNUSED_DEST)) \1406FAIL_IF(push_inst(compiler, op_imm | RD(dst) | RS1(src1) | IMM_I(src2))); \1407} \1408else { \1409if (op & SLJIT_SET_Z) \1410FAIL_IF(push_inst(compiler, op_reg | RD(EQUAL_FLAG) | RS1(src1) | RS2(src2))); \1411if (!(flags & UNUSED_DEST)) \1412FAIL_IF(push_inst(compiler, op_reg | RD(dst) | RS1(src1) | RS2(src2))); \1413}14141415#define EMIT_SHIFT(imm, reg) \1416op_imm = (imm); \1417op_reg = (reg);14181419static SLJIT_INLINE sljit_s32 emit_single_op(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 flags,1420sljit_s32 dst, sljit_s32 src1, sljit_sw src2)1421{1422sljit_s32 is_overflow, is_carry, carry_src_r, is_handled, reg;1423sljit_ins op_imm, op_reg;1424#if (defined SLJIT_CONFIG_RISCV_64 && SLJIT_CONFIG_RISCV_64)1425sljit_ins word = (sljit_ins)(op & SLJIT_32) >> 5;1426#endif /* SLJIT_CONFIG_RISCV_64 */14271428SLJIT_ASSERT(WORD == 0 || WORD == 0x8);14291430switch (GET_OPCODE(op)) {1431case SLJIT_MOV:1432SLJIT_ASSERT(src1 == TMP_ZERO && !(flags & SRC2_IMM));1433if (dst != src2)1434return push_inst(compiler, ADDI | RD(dst) | RS1(src2) | IMM_I(0));1435return SLJIT_SUCCESS;14361437case SLJIT_MOV_U8:1438SLJIT_ASSERT(src1 == TMP_ZERO && !(flags & SRC2_IMM));1439if ((flags & (REG_DEST | REG2_SOURCE)) == (REG_DEST | REG2_SOURCE))1440return push_inst(compiler, ANDI | RD(dst) | RS1(src2) | IMM_I(0xff));1441SLJIT_ASSERT(dst == src2);1442return SLJIT_SUCCESS;14431444case SLJIT_MOV_S8:1445#if defined __riscv_zbb1446return push_inst(compiler, SEXTB | RD(dst) | RS1(src2));1447#else /* !__riscv_zbb */1448SLJIT_ASSERT(src1 == TMP_ZERO && !(flags & SRC2_IMM));1449if ((flags & (REG_DEST | REG2_SOURCE)) == (REG_DEST | REG2_SOURCE)) {1450FAIL_IF(push_inst(compiler, SLLI | WORD | RD(dst) | RS1(src2) | IMM_EXTEND(24)));1451return push_inst(compiler, SRAI | WORD | RD(dst) | RS1(dst) | IMM_EXTEND(24));1452}1453SLJIT_ASSERT(dst == src2);1454return SLJIT_SUCCESS;1455#endif /* __riscv_zbb */14561457case SLJIT_MOV_U16:1458#if defined __riscv_zbb1459return push_inst(compiler, ZEXTH | RD(dst) | RS1(src2));1460#else /* !__riscv_zbb */1461SLJIT_ASSERT(src1 == TMP_ZERO && !(flags & SRC2_IMM));1462if ((flags & (REG_DEST | REG2_SOURCE)) == (REG_DEST | REG2_SOURCE)) {1463FAIL_IF(push_inst(compiler, SLLI | WORD | RD(dst) | RS1(src2) | IMM_EXTEND(16)));1464return push_inst(compiler, SRLI | WORD | RD(dst) | RS1(dst) | IMM_EXTEND(16));1465}1466SLJIT_ASSERT(dst == src2);1467return SLJIT_SUCCESS;1468#endif /* __riscv_zbb */14691470case SLJIT_MOV_S16:1471#if defined __riscv_zbb1472return push_inst(compiler, SEXTH | RD(dst) | RS1(src2));1473#else /* !__riscv_zbb */1474SLJIT_ASSERT(src1 == TMP_ZERO && !(flags & SRC2_IMM));1475if ((flags & (REG_DEST | REG2_SOURCE)) == (REG_DEST | REG2_SOURCE)) {1476FAIL_IF(push_inst(compiler, SLLI | WORD | RD(dst) | RS1(src2) | IMM_EXTEND(16)));1477return push_inst(compiler, SRAI | WORD | RD(dst) | RS1(dst) | IMM_EXTEND(16));1478}1479SLJIT_ASSERT(dst == src2);1480return SLJIT_SUCCESS;1481#endif /* !__riscv_zbb */14821483#if (defined SLJIT_CONFIG_RISCV_64 && SLJIT_CONFIG_RISCV_64)1484case SLJIT_MOV_U32:1485SLJIT_ASSERT(src1 == TMP_ZERO && !(flags & SRC2_IMM));1486if ((flags & (REG_DEST | REG2_SOURCE)) == (REG_DEST | REG2_SOURCE)) {1487FAIL_IF(push_inst(compiler, SLLI | RD(dst) | RS1(src2) | IMM_I(32)));1488return push_inst(compiler, SRLI | RD(dst) | RS1(dst) | IMM_I(32));1489}1490SLJIT_ASSERT(dst == src2);1491return SLJIT_SUCCESS;14921493case SLJIT_MOV_S32:1494SLJIT_ASSERT(src1 == TMP_ZERO && !(flags & SRC2_IMM));1495if ((flags & (REG_DEST | REG2_SOURCE)) == (REG_DEST | REG2_SOURCE))1496return push_inst(compiler, ADDI | 0x8 | RD(dst) | RS1(src2) | IMM_I(0));1497SLJIT_ASSERT(dst == src2);1498return SLJIT_SUCCESS;1499#endif /* SLJIT_CONFIG_RISCV_64 */15001501case SLJIT_CLZ:1502#if defined __riscv_zbb1503return push_inst(compiler, CLZ | WORD | RD(dst) | RS1(src2));1504#endif /* __riscv_zbb */1505case SLJIT_CTZ:1506#if defined __riscv_zbb1507return push_inst(compiler, CTZ | WORD | RD(dst) | RS1(src2));1508#else /* !__riscv_zbb */1509SLJIT_ASSERT(src1 == TMP_ZERO && !(flags & SRC2_IMM));1510return emit_clz_ctz(compiler, op, dst, src2);1511#endif /* __riscv_zbb */15121513case SLJIT_REV:1514#if defined __riscv_zbb1515SLJIT_ASSERT(src1 == TMP_ZERO && !(flags & SRC2_IMM));1516FAIL_IF(push_inst(compiler, REV8 | RD(dst) | RS1(src2)));1517#if defined SLJIT_CONFIG_RISCV_64 && SLJIT_CONFIG_RISCV_641518if (op & SLJIT_32)1519return push_inst(compiler, SRAI | RD(dst) | RS1(dst) | IMM_I(32));1520return SLJIT_SUCCESS;1521#else /* !SLJIT_CONFIG_RISCV_64 */1522return SLJIT_SUCCESS;1523#endif /* SLJIT_CONFIG_RISCV_64 */1524#endif /* __riscv_zbb */1525case SLJIT_REV_S32:1526#if ((defined SLJIT_CONFIG_RISCV_32 && SLJIT_CONFIG_RISCV_32) || defined __riscv_zbb)1527case SLJIT_REV_U32:1528#endif /* SLJIT_CONFIG_RISCV_32 || __riscv_zbb */1529SLJIT_ASSERT(src1 == TMP_ZERO && !(flags & SRC2_IMM));1530#if defined __riscv_zbb1531FAIL_IF(push_inst(compiler, REV8 | RD(dst) | RS1(src2)));1532#if defined SLJIT_CONFIG_RISCV_64 && SLJIT_CONFIG_RISCV_641533return push_inst(compiler, (GET_OPCODE(op) == SLJIT_REV_U32 ? SRLI : SRAI )| RD(dst) | RS1(dst) | IMM_I(32));1534#else /* !SLJIT_CONFIG_RISCV_64 */1535return SLJIT_SUCCESS;1536#endif /* SLJIT_CONFIG_RISCV_64 */1537#else /* !__riscv_zbb */1538return emit_rev(compiler, op, dst, src2);1539#endif /* __riscv_zbb */1540case SLJIT_REV_U16:1541case SLJIT_REV_S16:1542SLJIT_ASSERT(src1 == TMP_ZERO && !(flags & SRC2_IMM));1543#if defined __riscv_zbb1544FAIL_IF(push_inst(compiler, REV8 | RD(dst) | RS1(src2)));1545#if defined SLJIT_CONFIG_RISCV_64 && SLJIT_CONFIG_RISCV_641546return push_inst(compiler, (GET_OPCODE(op) == SLJIT_REV_U16 ? SRLI : SRAI )| RD(dst) | RS1(dst) | IMM_I(48));1547#else /* !SLJIT_CONFIG_RISCV_64 */1548return push_inst(compiler, (GET_OPCODE(op) == SLJIT_REV_U16 ? SRLI : SRAI) | RD(dst) | RS1(dst) | IMM_I(16));1549#endif /* SLJIT_CONFIG_RISCV_64 */1550#else /* !__riscv_zbb */1551return emit_rev16(compiler, op, dst, src2);1552#endif /* __riscv_zbb */15531554#if ((defined SLJIT_CONFIG_RISCV_64 && SLJIT_CONFIG_RISCV_64) && !defined __riscv_zbb)1555case SLJIT_REV_U32:1556SLJIT_ASSERT(src1 == TMP_ZERO && !(flags & SRC2_IMM) && dst != TMP_REG1);1557FAIL_IF(emit_rev(compiler, op, dst, src2));1558if (dst == TMP_REG2)1559return SLJIT_SUCCESS;1560FAIL_IF(push_inst(compiler, SLLI | RD(dst) | RS1(dst) | IMM_I(32)));1561return push_inst(compiler, SRLI | RD(dst) | RS1(dst) | IMM_I(32));1562#endif /* SLJIT_CONFIG_RISCV_64 && !__riscv_zbb */1563case SLJIT_ADD:1564/* Overflow computation (both add and sub): overflow = src1_sign ^ src2_sign ^ result_sign ^ carry_flag */1565is_overflow = GET_FLAG_TYPE(op) == SLJIT_OVERFLOW;1566carry_src_r = GET_FLAG_TYPE(op) == SLJIT_CARRY;15671568if (flags & SRC2_IMM) {1569if (is_overflow) {1570if (src2 >= 0)1571FAIL_IF(push_inst(compiler, ADDI | RD(EQUAL_FLAG) | RS1(src1) | IMM_I(0)));1572else1573FAIL_IF(push_inst(compiler, XORI | RD(EQUAL_FLAG) | RS1(src1) | IMM_I(-1)));1574}1575else if (op & SLJIT_SET_Z)1576FAIL_IF(push_inst(compiler, ADDI | WORD | RD(EQUAL_FLAG) | RS1(src1) | IMM_I(src2)));15771578/* Only the zero flag is needed. */1579if (!(flags & UNUSED_DEST) || (op & VARIABLE_FLAG_MASK))1580FAIL_IF(push_inst(compiler, ADDI | WORD | RD(dst) | RS1(src1) | IMM_I(src2)));1581}1582else {1583if (is_overflow)1584FAIL_IF(push_inst(compiler, XOR | RD(EQUAL_FLAG) | RS1(src1) | RS2(src2)));1585else if (op & SLJIT_SET_Z)1586FAIL_IF(push_inst(compiler, ADD | WORD | RD(EQUAL_FLAG) | RS1(src1) | RS2(src2)));15871588if (is_overflow || carry_src_r != 0) {1589if (src1 != dst)1590carry_src_r = (sljit_s32)src1;1591else if (src2 != dst)1592carry_src_r = (sljit_s32)src2;1593else {1594FAIL_IF(push_inst(compiler, ADDI | RD(OTHER_FLAG) | RS1(src1) | IMM_I(0)));1595carry_src_r = OTHER_FLAG;1596}1597}15981599/* Only the zero flag is needed. */1600if (!(flags & UNUSED_DEST) || (op & VARIABLE_FLAG_MASK))1601FAIL_IF(push_inst(compiler, ADD | WORD | RD(dst) | RS1(src1) | RS2(src2)));1602}16031604/* Carry is zero if a + b >= a or a + b >= b, otherwise it is 1. */1605if (is_overflow || carry_src_r != 0) {1606if (flags & SRC2_IMM)1607FAIL_IF(push_inst(compiler, SLTUI | RD(OTHER_FLAG) | RS1(dst) | IMM_I(src2)));1608else1609FAIL_IF(push_inst(compiler, SLTU | RD(OTHER_FLAG) | RS1(dst) | RS2(carry_src_r)));1610}16111612if (!is_overflow)1613return SLJIT_SUCCESS;16141615FAIL_IF(push_inst(compiler, XOR | RD(TMP_REG1) | RS1(dst) | RS2(EQUAL_FLAG)));1616if (op & SLJIT_SET_Z)1617FAIL_IF(push_inst(compiler, ADDI | RD(EQUAL_FLAG) | RS1(dst) | IMM_I(0)));1618FAIL_IF(push_inst(compiler, SRLI | WORD | RD(TMP_REG1) | RS1(TMP_REG1) | IMM_EXTEND(31)));1619return push_inst(compiler, XOR | RD(OTHER_FLAG) | RS1(TMP_REG1) | RS2(OTHER_FLAG));16201621case SLJIT_ADDC:1622carry_src_r = GET_FLAG_TYPE(op) == SLJIT_CARRY;16231624if (flags & SRC2_IMM) {1625FAIL_IF(push_inst(compiler, ADDI | WORD | RD(dst) | RS1(src1) | IMM_I(src2)));1626} else {1627if (carry_src_r != 0) {1628if (src1 != dst)1629carry_src_r = (sljit_s32)src1;1630else if (src2 != dst)1631carry_src_r = (sljit_s32)src2;1632else {1633FAIL_IF(push_inst(compiler, ADDI | RD(EQUAL_FLAG) | RS1(src1) | IMM_I(0)));1634carry_src_r = EQUAL_FLAG;1635}1636}16371638FAIL_IF(push_inst(compiler, ADD | WORD | RD(dst) | RS1(src1) | RS2(src2)));1639}16401641/* Carry is zero if a + b >= a or a + b >= b, otherwise it is 1. */1642if (carry_src_r != 0) {1643if (flags & SRC2_IMM)1644FAIL_IF(push_inst(compiler, SLTUI | RD(EQUAL_FLAG) | RS1(dst) | IMM_I(src2)));1645else1646FAIL_IF(push_inst(compiler, SLTU | RD(EQUAL_FLAG) | RS1(dst) | RS2(carry_src_r)));1647}16481649FAIL_IF(push_inst(compiler, ADD | WORD | RD(dst) | RS1(dst) | RS2(OTHER_FLAG)));16501651if (carry_src_r == 0)1652return SLJIT_SUCCESS;16531654/* Set ULESS_FLAG (dst == 0) && (OTHER_FLAG == 1). */1655FAIL_IF(push_inst(compiler, SLTU | RD(OTHER_FLAG) | RS1(dst) | RS2(OTHER_FLAG)));1656/* Set carry flag. */1657return push_inst(compiler, OR | RD(OTHER_FLAG) | RS1(OTHER_FLAG) | RS2(EQUAL_FLAG));16581659case SLJIT_SUB:1660if ((flags & SRC2_IMM) && src2 == SIMM_MIN) {1661FAIL_IF(push_inst(compiler, ADDI | RD(TMP_REG2) | RS1(TMP_ZERO) | IMM_I(src2)));1662src2 = TMP_REG2;1663flags &= ~SRC2_IMM;1664}16651666is_handled = 0;16671668if (flags & SRC2_IMM) {1669if (GET_FLAG_TYPE(op) == SLJIT_LESS) {1670FAIL_IF(push_inst(compiler, SLTUI | RD(OTHER_FLAG) | RS1(src1) | IMM_I(src2)));1671is_handled = 1;1672}1673else if (GET_FLAG_TYPE(op) == SLJIT_SIG_LESS) {1674FAIL_IF(push_inst(compiler, SLTI | RD(OTHER_FLAG) | RS1(src1) | IMM_I(src2)));1675is_handled = 1;1676}1677}16781679if (!is_handled && GET_FLAG_TYPE(op) >= SLJIT_LESS && GET_FLAG_TYPE(op) <= SLJIT_SIG_LESS_EQUAL) {1680is_handled = 1;16811682if (flags & SRC2_IMM) {1683reg = (src1 == TMP_REG1) ? TMP_REG2 : TMP_REG1;1684FAIL_IF(push_inst(compiler, ADDI | RD(reg) | RS1(TMP_ZERO) | IMM_I(src2)));1685src2 = reg;1686flags &= ~SRC2_IMM;1687}16881689switch (GET_FLAG_TYPE(op)) {1690case SLJIT_LESS:1691FAIL_IF(push_inst(compiler, SLTU | RD(OTHER_FLAG) | RS1(src1) | RS2(src2)));1692break;1693case SLJIT_GREATER:1694FAIL_IF(push_inst(compiler, SLTU | RD(OTHER_FLAG) | RS1(src2) | RS2(src1)));1695break;1696case SLJIT_SIG_LESS:1697FAIL_IF(push_inst(compiler, SLT | RD(OTHER_FLAG) | RS1(src1) | RS2(src2)));1698break;1699case SLJIT_SIG_GREATER:1700FAIL_IF(push_inst(compiler, SLT | RD(OTHER_FLAG) | RS1(src2) | RS2(src1)));1701break;1702}1703}17041705if (is_handled) {1706if (flags & SRC2_IMM) {1707if (op & SLJIT_SET_Z)1708FAIL_IF(push_inst(compiler, ADDI | WORD | RD(EQUAL_FLAG) | RS1(src1) | IMM_I(-src2)));1709if (!(flags & UNUSED_DEST))1710return push_inst(compiler, ADDI | WORD | RD(dst) | RS1(src1) | IMM_I(-src2));1711}1712else {1713if (op & SLJIT_SET_Z)1714FAIL_IF(push_inst(compiler, SUB | WORD | RD(EQUAL_FLAG) | RS1(src1) | RS2(src2)));1715if (!(flags & UNUSED_DEST))1716return push_inst(compiler, SUB | WORD | RD(dst) | RS1(src1) | RS2(src2));1717}1718return SLJIT_SUCCESS;1719}17201721is_overflow = GET_FLAG_TYPE(op) == SLJIT_OVERFLOW;1722is_carry = GET_FLAG_TYPE(op) == SLJIT_CARRY;17231724if (flags & SRC2_IMM) {1725if (is_overflow) {1726if (src2 >= 0)1727FAIL_IF(push_inst(compiler, ADDI | RD(EQUAL_FLAG) | RS1(src1) | IMM_I(0)));1728else1729FAIL_IF(push_inst(compiler, XORI | RD(EQUAL_FLAG) | RS1(src1) | IMM_I(-1)));1730}1731else if (op & SLJIT_SET_Z)1732FAIL_IF(push_inst(compiler, ADDI | WORD | RD(EQUAL_FLAG) | RS1(src1) | IMM_I(-src2)));17331734if (is_overflow || is_carry)1735FAIL_IF(push_inst(compiler, SLTUI | RD(OTHER_FLAG) | RS1(src1) | IMM_I(src2)));17361737/* Only the zero flag is needed. */1738if (!(flags & UNUSED_DEST) || (op & VARIABLE_FLAG_MASK))1739FAIL_IF(push_inst(compiler, ADDI | WORD | RD(dst) | RS1(src1) | IMM_I(-src2)));1740}1741else {1742if (is_overflow)1743FAIL_IF(push_inst(compiler, XOR | RD(EQUAL_FLAG) | RS1(src1) | RS2(src2)));1744else if (op & SLJIT_SET_Z)1745FAIL_IF(push_inst(compiler, SUB | WORD | RD(EQUAL_FLAG) | RS1(src1) | RS2(src2)));17461747if (is_overflow || is_carry)1748FAIL_IF(push_inst(compiler, SLTU | RD(OTHER_FLAG) | RS1(src1) | RS2(src2)));17491750/* Only the zero flag is needed. */1751if (!(flags & UNUSED_DEST) || (op & VARIABLE_FLAG_MASK))1752FAIL_IF(push_inst(compiler, SUB | WORD | RD(dst) | RS1(src1) | RS2(src2)));1753}17541755if (!is_overflow)1756return SLJIT_SUCCESS;17571758FAIL_IF(push_inst(compiler, XOR | RD(TMP_REG1) | RS1(dst) | RS2(EQUAL_FLAG)));1759if (op & SLJIT_SET_Z)1760FAIL_IF(push_inst(compiler, ADDI | RD(EQUAL_FLAG) | RS1(dst) | IMM_I(0)));1761FAIL_IF(push_inst(compiler, SRLI | WORD | RD(TMP_REG1) | RS1(TMP_REG1) | IMM_EXTEND(31)));1762return push_inst(compiler, XOR | RD(OTHER_FLAG) | RS1(TMP_REG1) | RS2(OTHER_FLAG));17631764case SLJIT_SUBC:1765if ((flags & SRC2_IMM) && src2 == SIMM_MIN) {1766FAIL_IF(push_inst(compiler, ADDI | RD(TMP_REG2) | RS1(TMP_ZERO) | IMM_I(src2)));1767src2 = TMP_REG2;1768flags &= ~SRC2_IMM;1769}17701771is_carry = GET_FLAG_TYPE(op) == SLJIT_CARRY;17721773if (flags & SRC2_IMM) {1774if (is_carry)1775FAIL_IF(push_inst(compiler, SLTUI | RD(EQUAL_FLAG) | RS1(src1) | IMM_I(src2)));17761777FAIL_IF(push_inst(compiler, ADDI | WORD | RD(dst) | RS1(src1) | IMM_I(-src2)));1778}1779else {1780if (is_carry)1781FAIL_IF(push_inst(compiler, SLTU | RD(EQUAL_FLAG) | RS1(src1) | RS2(src2)));17821783FAIL_IF(push_inst(compiler, SUB | WORD | RD(dst) | RS1(src1) | RS2(src2)));1784}17851786if (is_carry)1787FAIL_IF(push_inst(compiler, SLTU | RD(TMP_REG1) | RS1(dst) | RS2(OTHER_FLAG)));17881789FAIL_IF(push_inst(compiler, SUB | WORD | RD(dst) | RS1(dst) | RS2(OTHER_FLAG)));17901791if (!is_carry)1792return SLJIT_SUCCESS;17931794return push_inst(compiler, OR | RD(OTHER_FLAG) | RS1(EQUAL_FLAG) | RS2(TMP_REG1));17951796case SLJIT_MUL:1797SLJIT_ASSERT(!(flags & SRC2_IMM));17981799if (GET_FLAG_TYPE(op) != SLJIT_OVERFLOW)1800return push_inst(compiler, MUL | WORD | RD(dst) | RS1(src1) | RS2(src2));18011802#if (defined SLJIT_CONFIG_RISCV_64 && SLJIT_CONFIG_RISCV_64)1803if (word) {1804FAIL_IF(push_inst(compiler, MUL | RD(OTHER_FLAG) | RS1(src1) | RS2(src2)));1805FAIL_IF(push_inst(compiler, MUL | 0x8 | RD(dst) | RS1(src1) | RS2(src2)));1806return push_inst(compiler, SUB | RD(OTHER_FLAG) | RS1(dst) | RS2(OTHER_FLAG));1807}1808#endif /* SLJIT_CONFIG_RISCV_64 */18091810FAIL_IF(push_inst(compiler, MULH | RD(EQUAL_FLAG) | RS1(src1) | RS2(src2)));1811FAIL_IF(push_inst(compiler, MUL | RD(dst) | RS1(src1) | RS2(src2)));1812#if (defined SLJIT_CONFIG_RISCV_32 && SLJIT_CONFIG_RISCV_32)1813FAIL_IF(push_inst(compiler, SRAI | RD(OTHER_FLAG) | RS1(dst) | IMM_I(31)));1814#else /* !SLJIT_CONFIG_RISCV_32 */1815FAIL_IF(push_inst(compiler, SRAI | RD(OTHER_FLAG) | RS1(dst) | IMM_I(63)));1816#endif /* SLJIT_CONFIG_RISCV_32 */1817return push_inst(compiler, SUB | RD(OTHER_FLAG) | RS1(EQUAL_FLAG) | RS2(OTHER_FLAG));18181819case SLJIT_AND:1820EMIT_LOGICAL(ANDI, AND);1821return SLJIT_SUCCESS;18221823case SLJIT_OR:1824EMIT_LOGICAL(ORI, OR);1825return SLJIT_SUCCESS;18261827case SLJIT_XOR:1828EMIT_LOGICAL(XORI, XOR);1829return SLJIT_SUCCESS;18301831case SLJIT_SHL:1832case SLJIT_MSHL:1833EMIT_SHIFT(SLLI, SLL);1834break;18351836case SLJIT_LSHR:1837case SLJIT_MLSHR:1838EMIT_SHIFT(SRLI, SRL);1839break;18401841case SLJIT_ASHR:1842case SLJIT_MASHR:1843EMIT_SHIFT(SRAI, SRA);1844break;18451846case SLJIT_ROTL:1847case SLJIT_ROTR:1848if (flags & SRC2_IMM) {1849SLJIT_ASSERT(src2 != 0);1850#if defined __riscv_zbb1851if (GET_OPCODE(op) == SLJIT_ROTL) {1852#if (defined SLJIT_CONFIG_RISCV_64 && SLJIT_CONFIG_RISCV_64)1853src2 = ((op & SLJIT_32) ? 32 : 64) - src2;1854#else /* !SLJIT_CONFIG_RISCV_64 */1855src2 = 32 - src2;1856#endif /* SLJIT_CONFIG_RISCV_64 */1857}1858return push_inst(compiler, RORI | WORD | RD(dst) | RS1(src1) | IMM_I(src2));1859#else /* !__riscv_zbb */1860op_imm = (GET_OPCODE(op) == SLJIT_ROTL) ? SLLI : SRLI;1861FAIL_IF(push_inst(compiler, op_imm | WORD | RD(OTHER_FLAG) | RS1(src1) | IMM_I(src2)));18621863#if (defined SLJIT_CONFIG_RISCV_64 && SLJIT_CONFIG_RISCV_64)1864src2 = ((op & SLJIT_32) ? 32 : 64) - src2;1865#else /* !SLJIT_CONFIG_RISCV_64 */1866src2 = 32 - src2;1867#endif /* SLJIT_CONFIG_RISCV_64 */1868op_imm = (GET_OPCODE(op) == SLJIT_ROTL) ? SRLI : SLLI;1869FAIL_IF(push_inst(compiler, op_imm | WORD | RD(dst) | RS1(src1) | IMM_I(src2)));1870return push_inst(compiler, OR | RD(dst) | RS1(dst) | RS2(OTHER_FLAG));1871#endif /* !__riscv_zbb */1872}18731874#if defined __riscv_zbb1875return push_inst(compiler, (GET_OPCODE(op) == SLJIT_ROTL ? ROL : ROR) | WORD | RD(dst) | RS1(src1) | RS2(src2));1876#else /* !__riscv_zbb */1877if (src2 == TMP_ZERO) {1878if (dst != src1)1879return push_inst(compiler, ADDI | WORD | RD(dst) | RS1(src1) | IMM_I(0));1880return SLJIT_SUCCESS;1881}18821883FAIL_IF(push_inst(compiler, SUB | WORD | RD(EQUAL_FLAG) | RS1(TMP_ZERO) | RS2(src2)));1884op_reg = (GET_OPCODE(op) == SLJIT_ROTL) ? SLL : SRL;1885FAIL_IF(push_inst(compiler, op_reg | WORD | RD(OTHER_FLAG) | RS1(src1) | RS2(src2)));1886op_reg = (GET_OPCODE(op) == SLJIT_ROTL) ? SRL : SLL;1887FAIL_IF(push_inst(compiler, op_reg | WORD | RD(dst) | RS1(src1) | RS2(EQUAL_FLAG)));1888return push_inst(compiler, OR | RD(dst) | RS1(dst) | RS2(OTHER_FLAG));1889#endif /* !riscv_zbb */1890default:1891SLJIT_UNREACHABLE();1892return SLJIT_SUCCESS;1893}18941895if (flags & SRC2_IMM) {1896if (op & SLJIT_SET_Z)1897FAIL_IF(push_inst(compiler, op_imm | WORD | RD(EQUAL_FLAG) | RS1(src1) | IMM_I(src2)));18981899if (flags & UNUSED_DEST)1900return SLJIT_SUCCESS;1901return push_inst(compiler, op_imm | WORD | RD(dst) | RS1(src1) | IMM_I(src2));1902}19031904if (op & SLJIT_SET_Z)1905FAIL_IF(push_inst(compiler, op_reg | WORD | RD(EQUAL_FLAG) | RS1(src1) | RS2(src2)));19061907if (flags & UNUSED_DEST)1908return SLJIT_SUCCESS;1909return push_inst(compiler, op_reg | WORD | RD(dst) | RS1(src1) | RS2(src2));1910}19111912#undef IMM_EXTEND19131914static sljit_s32 emit_op(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 flags,1915sljit_s32 dst, sljit_sw dstw,1916sljit_s32 src1, sljit_sw src1w,1917sljit_s32 src2, sljit_sw src2w)1918{1919/* arg1 goes to TMP_REG1 or src reg1920arg2 goes to TMP_REG2, imm or src reg1921TMP_REG3 can be used for caching1922result goes to TMP_REG2, so put result can use TMP_REG1 and TMP_REG3. */1923sljit_s32 dst_r = TMP_REG2;1924sljit_s32 src1_r;1925sljit_sw src2_r = 0;1926sljit_s32 src2_tmp_reg = (GET_OPCODE(op) >= SLJIT_OP2_BASE && FAST_IS_REG(src1)) ? TMP_REG1 : TMP_REG2;19271928if (!(flags & ALT_KEEP_CACHE)) {1929compiler->cache_arg = 0;1930compiler->cache_argw = 0;1931}19321933if (dst == 0) {1934SLJIT_ASSERT(HAS_FLAGS(op));1935flags |= UNUSED_DEST;1936dst = TMP_REG2;1937}1938else if (FAST_IS_REG(dst)) {1939dst_r = dst;1940flags |= REG_DEST;1941if (flags & MOVE_OP)1942src2_tmp_reg = dst_r;1943}1944else if ((dst & SLJIT_MEM) && !getput_arg_fast(compiler, flags | ARG_TEST, TMP_REG1, dst, dstw))1945flags |= SLOW_DEST;19461947if (flags & IMM_OP) {1948if (src2 == SLJIT_IMM && src2w != 0 && src2w <= SIMM_MAX && src2w >= SIMM_MIN) {1949flags |= SRC2_IMM;1950src2_r = src2w;1951}1952else if ((flags & CUMULATIVE_OP) && src1 == SLJIT_IMM && src1w != 0 && src1w <= SIMM_MAX && src1w >= SIMM_MIN) {1953flags |= SRC2_IMM;1954src2_r = src1w;19551956/* And swap arguments. */1957src1 = src2;1958src1w = src2w;1959src2 = SLJIT_IMM;1960/* src2w = src2_r unneeded. */1961}1962}19631964/* Source 1. */1965if (FAST_IS_REG(src1)) {1966src1_r = src1;1967flags |= REG1_SOURCE;1968} else if (src1 == SLJIT_IMM) {1969if (src1w) {1970FAIL_IF(load_immediate(compiler, TMP_REG1, src1w, TMP_REG3));1971src1_r = TMP_REG1;1972}1973else1974src1_r = TMP_ZERO;1975} else {1976if (getput_arg_fast(compiler, flags | LOAD_DATA, TMP_REG1, src1, src1w))1977FAIL_IF(compiler->error);1978else1979flags |= SLOW_SRC1;1980src1_r = TMP_REG1;1981}19821983/* Source 2. */1984if (FAST_IS_REG(src2)) {1985src2_r = src2;1986flags |= REG2_SOURCE;1987if ((flags & (REG_DEST | MOVE_OP)) == MOVE_OP)1988dst_r = (sljit_s32)src2_r;1989} else if (src2 == SLJIT_IMM) {1990if (!(flags & SRC2_IMM)) {1991if (src2w) {1992FAIL_IF(load_immediate(compiler, src2_tmp_reg, src2w, TMP_REG3));1993src2_r = src2_tmp_reg;1994} else {1995src2_r = TMP_ZERO;1996if (flags & MOVE_OP) {1997if (dst & SLJIT_MEM)1998dst_r = 0;1999else2000op = SLJIT_MOV;2001}2002}2003}2004} else {2005if (getput_arg_fast(compiler, flags | LOAD_DATA, src2_tmp_reg, src2, src2w))2006FAIL_IF(compiler->error);2007else2008flags |= SLOW_SRC2;2009src2_r = src2_tmp_reg;2010}20112012if ((flags & (SLOW_SRC1 | SLOW_SRC2)) == (SLOW_SRC1 | SLOW_SRC2)) {2013SLJIT_ASSERT(src2_r == TMP_REG2);2014if ((flags & SLOW_DEST) && !can_cache(src2, src2w, src1, src1w) && can_cache(src2, src2w, dst, dstw)) {2015FAIL_IF(getput_arg(compiler, flags | LOAD_DATA, TMP_REG1, src1, src1w, src2, src2w));2016FAIL_IF(getput_arg(compiler, flags | LOAD_DATA | MEM_USE_TMP2, TMP_REG2, src2, src2w, dst, dstw));2017} else {2018FAIL_IF(getput_arg(compiler, flags | LOAD_DATA, TMP_REG2, src2, src2w, src1, src1w));2019FAIL_IF(getput_arg(compiler, flags | LOAD_DATA, TMP_REG1, src1, src1w, dst, dstw));2020}2021}2022else if (flags & SLOW_SRC1)2023FAIL_IF(getput_arg(compiler, flags | LOAD_DATA, TMP_REG1, src1, src1w, dst, dstw));2024else if (flags & SLOW_SRC2)2025FAIL_IF(getput_arg(compiler, flags | LOAD_DATA | ((src1_r == TMP_REG1) ? MEM_USE_TMP2 : 0), src2_tmp_reg, src2, src2w, dst, dstw));20262027FAIL_IF(emit_single_op(compiler, op, flags, dst_r, src1_r, src2_r));20282029if (dst & SLJIT_MEM) {2030if (!(flags & SLOW_DEST)) {2031getput_arg_fast(compiler, flags, dst_r, dst, dstw);2032return compiler->error;2033}2034return getput_arg(compiler, flags, dst_r, dst, dstw, 0, 0);2035}20362037return SLJIT_SUCCESS;2038}20392040SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op0(struct sljit_compiler *compiler, sljit_s32 op)2041{2042#if (defined SLJIT_CONFIG_RISCV_64 && SLJIT_CONFIG_RISCV_64)2043sljit_ins word = (sljit_ins)(op & SLJIT_32) >> 5;20442045SLJIT_ASSERT(word == 0 || word == 0x8);2046#endif /* SLJIT_CONFIG_RISCV_64 */20472048CHECK_ERROR();2049CHECK(check_sljit_emit_op0(compiler, op));20502051switch (GET_OPCODE(op)) {2052case SLJIT_BREAKPOINT:2053return push_inst(compiler, EBREAK);2054case SLJIT_NOP:2055return push_inst(compiler, ADDI | RD(TMP_ZERO) | RS1(TMP_ZERO) | IMM_I(0));2056case SLJIT_LMUL_UW:2057FAIL_IF(push_inst(compiler, ADDI | RD(TMP_REG1) | RS1(SLJIT_R1) | IMM_I(0)));2058FAIL_IF(push_inst(compiler, MULHU | RD(SLJIT_R1) | RS1(SLJIT_R0) | RS2(SLJIT_R1)));2059return push_inst(compiler, MUL | RD(SLJIT_R0) | RS1(SLJIT_R0) | RS2(TMP_REG1));2060case SLJIT_LMUL_SW:2061FAIL_IF(push_inst(compiler, ADDI | RD(TMP_REG1) | RS1(SLJIT_R1) | IMM_I(0)));2062FAIL_IF(push_inst(compiler, MULH | RD(SLJIT_R1) | RS1(SLJIT_R0) | RS2(SLJIT_R1)));2063return push_inst(compiler, MUL | RD(SLJIT_R0) | RS1(SLJIT_R0) | RS2(TMP_REG1));2064case SLJIT_DIVMOD_UW:2065FAIL_IF(push_inst(compiler, ADDI | RD(TMP_REG1) | RS1(SLJIT_R0) | IMM_I(0)));2066FAIL_IF(push_inst(compiler, DIVU | WORD | RD(SLJIT_R0) | RS1(SLJIT_R0) | RS2(SLJIT_R1)));2067return push_inst(compiler, REMU | WORD | RD(SLJIT_R1) | RS1(TMP_REG1) | RS2(SLJIT_R1));2068case SLJIT_DIVMOD_SW:2069FAIL_IF(push_inst(compiler, ADDI | RD(TMP_REG1) | RS1(SLJIT_R0) | IMM_I(0)));2070FAIL_IF(push_inst(compiler, DIV | WORD | RD(SLJIT_R0) | RS1(SLJIT_R0) | RS2(SLJIT_R1)));2071return push_inst(compiler, REM | WORD | RD(SLJIT_R1) | RS1(TMP_REG1) | RS2(SLJIT_R1));2072case SLJIT_DIV_UW:2073return push_inst(compiler, DIVU | WORD | RD(SLJIT_R0) | RS1(SLJIT_R0) | RS2(SLJIT_R1));2074case SLJIT_DIV_SW:2075return push_inst(compiler, DIV | WORD | RD(SLJIT_R0) | RS1(SLJIT_R0) | RS2(SLJIT_R1));2076case SLJIT_MEMORY_BARRIER:2077return push_inst(compiler, FENCE | 0x0ff00000);2078case SLJIT_ENDBR:2079case SLJIT_SKIP_FRAMES_BEFORE_RETURN:2080return SLJIT_SUCCESS;2081}20822083return SLJIT_SUCCESS;2084}20852086SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op1(struct sljit_compiler *compiler, sljit_s32 op,2087sljit_s32 dst, sljit_sw dstw,2088sljit_s32 src, sljit_sw srcw)2089{2090sljit_s32 flags = 0;20912092CHECK_ERROR();2093CHECK(check_sljit_emit_op1(compiler, op, dst, dstw, src, srcw));2094ADJUST_LOCAL_OFFSET(dst, dstw);2095ADJUST_LOCAL_OFFSET(src, srcw);20962097#if (defined SLJIT_CONFIG_RISCV_64 && SLJIT_CONFIG_RISCV_64)2098if (op & SLJIT_32)2099flags = INT_DATA | SIGNED_DATA;2100#endif /* SLJIT_CONFIG_RISCV_64 */21012102switch (GET_OPCODE(op)) {2103case SLJIT_MOV:2104#if (defined SLJIT_CONFIG_RISCV_32 && SLJIT_CONFIG_RISCV_32)2105case SLJIT_MOV_U32:2106case SLJIT_MOV_S32:2107case SLJIT_MOV32:2108#endif /* SLJIT_CONFIG_RISCV_32 */2109case SLJIT_MOV_P:2110return emit_op(compiler, SLJIT_MOV, WORD_DATA | MOVE_OP, dst, dstw, TMP_ZERO, 0, src, srcw);21112112#if (defined SLJIT_CONFIG_RISCV_64 && SLJIT_CONFIG_RISCV_64)2113case SLJIT_MOV_U32:2114return emit_op(compiler, SLJIT_MOV_U32, INT_DATA | MOVE_OP, dst, dstw, TMP_ZERO, 0, src, (src == SLJIT_IMM) ? (sljit_u32)srcw : srcw);21152116case SLJIT_MOV_S32:2117/* Logical operators have no W variant, so sign extended input is necessary for them. */2118case SLJIT_MOV32:2119return 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);2120#endif /* SLJIT_CONFIG_RISCV_64 */21212122case SLJIT_MOV_U8:2123return emit_op(compiler, op, BYTE_DATA | MOVE_OP, dst, dstw, TMP_ZERO, 0, src, (src == SLJIT_IMM) ? (sljit_u8)srcw : srcw);21242125case SLJIT_MOV_S8:2126return emit_op(compiler, op, BYTE_DATA | SIGNED_DATA | MOVE_OP, dst, dstw, TMP_ZERO, 0, src, (src == SLJIT_IMM) ? (sljit_s8)srcw : srcw);21272128case SLJIT_MOV_U16:2129return emit_op(compiler, op, HALF_DATA | MOVE_OP, dst, dstw, TMP_ZERO, 0, src, (src == SLJIT_IMM) ? (sljit_u16)srcw : srcw);21302131case SLJIT_MOV_S16:2132return emit_op(compiler, op, HALF_DATA | SIGNED_DATA | MOVE_OP, dst, dstw, TMP_ZERO, 0, src, (src == SLJIT_IMM) ? (sljit_s16)srcw : srcw);21332134case SLJIT_CLZ:2135case SLJIT_CTZ:2136case SLJIT_REV:2137return emit_op(compiler, op, flags, dst, dstw, TMP_ZERO, 0, src, srcw);21382139case SLJIT_REV_U16:2140case SLJIT_REV_S16:2141return emit_op(compiler, op, HALF_DATA, dst, dstw, TMP_ZERO, 0, src, srcw);21422143case SLJIT_REV_U32:2144case SLJIT_REV_S32:2145return emit_op(compiler, op | SLJIT_32, INT_DATA, dst, dstw, TMP_ZERO, 0, src, srcw);2146}21472148SLJIT_UNREACHABLE();2149return SLJIT_SUCCESS;2150}21512152SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op2(struct sljit_compiler *compiler, sljit_s32 op,2153sljit_s32 dst, sljit_sw dstw,2154sljit_s32 src1, sljit_sw src1w,2155sljit_s32 src2, sljit_sw src2w)2156{2157sljit_s32 flags = 0;21582159CHECK_ERROR();2160CHECK(check_sljit_emit_op2(compiler, op, 0, dst, dstw, src1, src1w, src2, src2w));2161ADJUST_LOCAL_OFFSET(dst, dstw);2162ADJUST_LOCAL_OFFSET(src1, src1w);2163ADJUST_LOCAL_OFFSET(src2, src2w);21642165#if (defined SLJIT_CONFIG_RISCV_64 && SLJIT_CONFIG_RISCV_64)2166if (op & SLJIT_32) {2167flags |= INT_DATA | SIGNED_DATA;2168if (src1 == SLJIT_IMM)2169src1w = (sljit_s32)src1w;2170if (src2 == SLJIT_IMM)2171src2w = (sljit_s32)src2w;2172}2173#endif /* SLJIT_CONFIG_RISCV_64 */21742175switch (GET_OPCODE(op)) {2176case SLJIT_ADD:2177case SLJIT_ADDC:2178compiler->status_flags_state = SLJIT_CURRENT_FLAGS_ADD;2179return emit_op(compiler, op, flags | CUMULATIVE_OP | IMM_OP, dst, dstw, src1, src1w, src2, src2w);21802181case SLJIT_SUB:2182case SLJIT_SUBC:2183compiler->status_flags_state = SLJIT_CURRENT_FLAGS_SUB;2184return emit_op(compiler, op, flags | IMM_OP, dst, dstw, src1, src1w, src2, src2w);21852186case SLJIT_MUL:2187compiler->status_flags_state = 0;2188return emit_op(compiler, op, flags | CUMULATIVE_OP, dst, dstw, src1, src1w, src2, src2w);21892190case SLJIT_AND:2191case SLJIT_OR:2192case SLJIT_XOR:2193return emit_op(compiler, op, flags | CUMULATIVE_OP | IMM_OP, dst, dstw, src1, src1w, src2, src2w);21942195case SLJIT_SHL:2196case SLJIT_MSHL:2197case SLJIT_LSHR:2198case SLJIT_MLSHR:2199case SLJIT_ASHR:2200case SLJIT_MASHR:2201case SLJIT_ROTL:2202case SLJIT_ROTR:2203if (src2 == SLJIT_IMM) {2204#if (defined SLJIT_CONFIG_RISCV_32 && SLJIT_CONFIG_RISCV_32)2205src2w &= 0x1f;2206#else /* !SLJIT_CONFIG_RISCV_32 */2207if (op & SLJIT_32)2208src2w &= 0x1f;2209else2210src2w &= 0x3f;2211#endif /* SLJIT_CONFIG_RISCV_32 */2212}22132214return emit_op(compiler, op, flags | IMM_OP, dst, dstw, src1, src1w, src2, src2w);2215}22162217SLJIT_UNREACHABLE();2218return SLJIT_SUCCESS;2219}22202221SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op2u(struct sljit_compiler *compiler, sljit_s32 op,2222sljit_s32 src1, sljit_sw src1w,2223sljit_s32 src2, sljit_sw src2w)2224{2225CHECK_ERROR();2226CHECK(check_sljit_emit_op2(compiler, op, 1, 0, 0, src1, src1w, src2, src2w));22272228SLJIT_SKIP_CHECKS(compiler);2229return sljit_emit_op2(compiler, op, 0, 0, src1, src1w, src2, src2w);2230}22312232SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op2r(struct sljit_compiler *compiler, sljit_s32 op,2233sljit_s32 dst_reg,2234sljit_s32 src1, sljit_sw src1w,2235sljit_s32 src2, sljit_sw src2w)2236{2237#if (defined SLJIT_CONFIG_RISCV_64 && SLJIT_CONFIG_RISCV_64)2238sljit_ins word = (sljit_ins)(op & SLJIT_32) >> 5;2239#endif /* SLJIT_CONFIG_RISCV_64 */22402241CHECK_ERROR();2242CHECK(check_sljit_emit_op2r(compiler, op, dst_reg, src1, src1w, src2, src2w));22432244SLJIT_ASSERT(WORD == 0 || WORD == 0x8);22452246switch (GET_OPCODE(op)) {2247case SLJIT_MULADD:2248SLJIT_SKIP_CHECKS(compiler);2249FAIL_IF(sljit_emit_op2(compiler, SLJIT_MUL | (op & SLJIT_32), TMP_REG2, 0, src1, src1w, src2, src2w));2250return push_inst(compiler, ADD | WORD | RD(dst_reg) | RS1(dst_reg) | RS2(TMP_REG2));2251}22522253return SLJIT_SUCCESS;2254}22552256SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_shift_into(struct sljit_compiler *compiler, sljit_s32 op,2257sljit_s32 dst_reg,2258sljit_s32 src1_reg,2259sljit_s32 src2_reg,2260sljit_s32 src3, sljit_sw src3w)2261{2262sljit_s32 is_left;2263sljit_ins ins1, ins2, ins3;2264#if (defined SLJIT_CONFIG_RISCV_64 && SLJIT_CONFIG_RISCV_64)2265sljit_ins word = (sljit_ins)(op & SLJIT_32) >> 5;2266sljit_s32 inp_flags = ((op & SLJIT_32) ? INT_DATA : WORD_DATA) | LOAD_DATA;2267sljit_sw bit_length = (op & SLJIT_32) ? 32 : 64;2268#else /* !SLJIT_CONFIG_RISCV_64 */2269sljit_s32 inp_flags = WORD_DATA | LOAD_DATA;2270sljit_sw bit_length = 32;2271#endif /* SLJIT_CONFIG_RISCV_64 */22722273SLJIT_ASSERT(WORD == 0 || WORD == 0x8);22742275CHECK_ERROR();2276CHECK(check_sljit_emit_shift_into(compiler, op, dst_reg, src1_reg, src2_reg, src3, src3w));22772278is_left = (GET_OPCODE(op) == SLJIT_SHL || GET_OPCODE(op) == SLJIT_MSHL);22792280if (src1_reg == src2_reg) {2281SLJIT_SKIP_CHECKS(compiler);2282return sljit_emit_op2(compiler, (is_left ? SLJIT_ROTL : SLJIT_ROTR) | (op & SLJIT_32), dst_reg, 0, src1_reg, 0, src3, src3w);2283}22842285ADJUST_LOCAL_OFFSET(src3, src3w);22862287if (src3 == SLJIT_IMM) {2288src3w &= bit_length - 1;22892290if (src3w == 0)2291return SLJIT_SUCCESS;22922293if (is_left) {2294ins1 = SLLI | WORD | IMM_I(src3w);2295src3w = bit_length - src3w;2296ins2 = SRLI | WORD | IMM_I(src3w);2297} else {2298ins1 = SRLI | WORD | IMM_I(src3w);2299src3w = bit_length - src3w;2300ins2 = SLLI | WORD | IMM_I(src3w);2301}23022303FAIL_IF(push_inst(compiler, ins1 | RD(dst_reg) | RS1(src1_reg)));2304FAIL_IF(push_inst(compiler, ins2 | RD(TMP_REG1) | RS1(src2_reg)));2305return push_inst(compiler, OR | RD(dst_reg) | RS1(dst_reg) | RS2(TMP_REG1));2306}23072308if (src3 & SLJIT_MEM) {2309FAIL_IF(emit_op_mem(compiler, inp_flags, TMP_REG2, src3, src3w));2310src3 = TMP_REG2;2311} else if (dst_reg == src3) {2312push_inst(compiler, ADDI | WORD | RD(TMP_REG2) | RS1(src3) | IMM_I(0));2313src3 = TMP_REG2;2314}23152316if (is_left) {2317ins1 = SLL;2318ins2 = SRLI;2319ins3 = SRL;2320} else {2321ins1 = SRL;2322ins2 = SLLI;2323ins3 = SLL;2324}23252326FAIL_IF(push_inst(compiler, ins1 | WORD | RD(dst_reg) | RS1(src1_reg) | RS2(src3)));23272328if (!(op & SLJIT_SHIFT_INTO_NON_ZERO)) {2329FAIL_IF(push_inst(compiler, ins2 | WORD | RD(TMP_REG1) | RS1(src2_reg) | IMM_I(1)));2330FAIL_IF(push_inst(compiler, XORI | RD(TMP_REG2) | RS1(src3) | IMM_I((sljit_ins)bit_length - 1)));2331src2_reg = TMP_REG1;2332} else2333FAIL_IF(push_inst(compiler, SUB | WORD | RD(TMP_REG2) | RS1(TMP_ZERO) | RS2(src3)));23342335FAIL_IF(push_inst(compiler, ins3 | WORD | RD(TMP_REG1) | RS1(src2_reg) | RS2(TMP_REG2)));2336return push_inst(compiler, OR | RD(dst_reg) | RS1(dst_reg) | RS2(TMP_REG1));2337}23382339SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_src(struct sljit_compiler *compiler, sljit_s32 op,2340sljit_s32 src, sljit_sw srcw)2341{2342CHECK_ERROR();2343CHECK(check_sljit_emit_op_src(compiler, op, src, srcw));2344ADJUST_LOCAL_OFFSET(src, srcw);23452346switch (op) {2347case SLJIT_FAST_RETURN:2348if (FAST_IS_REG(src))2349FAIL_IF(push_inst(compiler, ADDI | RD(RETURN_ADDR_REG) | RS1(src) | IMM_I(0)));2350else2351FAIL_IF(emit_op_mem(compiler, WORD_DATA | LOAD_DATA, RETURN_ADDR_REG, src, srcw));23522353return push_inst(compiler, JALR | RD(TMP_ZERO) | RS1(RETURN_ADDR_REG) | IMM_I(0));2354case SLJIT_SKIP_FRAMES_BEFORE_FAST_RETURN:2355return SLJIT_SUCCESS;2356case SLJIT_PREFETCH_L1:2357case SLJIT_PREFETCH_L2:2358case SLJIT_PREFETCH_L3:2359case SLJIT_PREFETCH_ONCE:2360return SLJIT_SUCCESS;2361}23622363return SLJIT_SUCCESS;2364}23652366SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_dst(struct sljit_compiler *compiler, sljit_s32 op,2367sljit_s32 dst, sljit_sw dstw)2368{2369sljit_s32 dst_r;23702371CHECK_ERROR();2372CHECK(check_sljit_emit_op_dst(compiler, op, dst, dstw));2373ADJUST_LOCAL_OFFSET(dst, dstw);23742375switch (op) {2376case SLJIT_FAST_ENTER:2377if (FAST_IS_REG(dst))2378return push_inst(compiler, ADDI | RD(dst) | RS1(RETURN_ADDR_REG) | IMM_I(0));23792380SLJIT_ASSERT(RETURN_ADDR_REG == TMP_REG2);2381break;2382case SLJIT_GET_RETURN_ADDRESS:2383dst_r = FAST_IS_REG(dst) ? dst : TMP_REG2;2384FAIL_IF(emit_op_mem(compiler, WORD_DATA | LOAD_DATA, dst_r, SLJIT_MEM1(SLJIT_SP), compiler->local_size - SSIZE_OF(sw)));2385break;2386}23872388if (dst & SLJIT_MEM)2389return emit_op_mem(compiler, WORD_DATA, TMP_REG2, dst, dstw);23902391return SLJIT_SUCCESS;2392}23932394SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_get_register_index(sljit_s32 type, sljit_s32 reg)2395{2396CHECK_REG_INDEX(check_sljit_get_register_index(type, reg));23972398if (type == SLJIT_GP_REGISTER)2399return reg_map[reg];24002401if (type == SLJIT_FLOAT_REGISTER)2402return freg_map[reg];24032404return vreg_map[reg];2405}24062407SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_custom(struct sljit_compiler *compiler,2408void *instruction, sljit_u32 size)2409{2410SLJIT_UNUSED_ARG(size);24112412CHECK_ERROR();2413CHECK(check_sljit_emit_op_custom(compiler, instruction, size));24142415return push_inst(compiler, *(sljit_ins*)instruction);2416}24172418/* --------------------------------------------------------------------- */2419/* Floating point operators */2420/* --------------------------------------------------------------------- */24212422#define FLOAT_DATA(op) (DOUBLE_DATA | ((op & SLJIT_32) >> 7))2423#define FMT(op) ((sljit_ins)((op & SLJIT_32) ^ SLJIT_32) << 17)24242425static SLJIT_INLINE sljit_s32 sljit_emit_fop1_conv_sw_from_f64(struct sljit_compiler *compiler, sljit_s32 op,2426sljit_s32 dst, sljit_sw dstw,2427sljit_s32 src, sljit_sw srcw)2428{2429#if (defined SLJIT_CONFIG_RISCV_32 && SLJIT_CONFIG_RISCV_32)2430# define flags (sljit_u32)02431#else /* !SLJIT_CONFIG_RISCV_32 */2432sljit_u32 flags = ((sljit_u32)(GET_OPCODE(op) == SLJIT_CONV_SW_FROM_F64)) << 21;2433#endif /* SLJIT_CONFIG_RISCV_32 */2434sljit_s32 dst_r = FAST_IS_REG(dst) ? dst : TMP_REG2;24352436if (src & SLJIT_MEM) {2437FAIL_IF(emit_op_mem2(compiler, FLOAT_DATA(op) | LOAD_DATA, TMP_FREG1, src, srcw, dst, dstw));2438src = TMP_FREG1;2439}24402441FAIL_IF(push_inst(compiler, FCVT_W_S | FMT(op) | flags | RD(dst_r) | FRS1(src)));24422443/* Store the integer value from a VFP register. */2444if (dst & SLJIT_MEM) {2445#if (defined SLJIT_CONFIG_RISCV_32 && SLJIT_CONFIG_RISCV_32)2446return emit_op_mem2(compiler, WORD_DATA, TMP_REG2, dst, dstw, 0, 0);2447#else /* !SLJIT_CONFIG_RISCV_32 */2448return emit_op_mem2(compiler, flags ? WORD_DATA : INT_DATA, TMP_REG2, dst, dstw, 0, 0);2449#endif /* SLJIT_CONFIG_RISCV_32 */2450}2451return SLJIT_SUCCESS;24522453#if (defined SLJIT_CONFIG_RISCV_32 && SLJIT_CONFIG_RISCV_32)2454# undef flags2455#endif /* SLJIT_CONFIG_RISCV_32 */2456}24572458static sljit_s32 sljit_emit_fop1_conv_f64_from_w(struct sljit_compiler *compiler, sljit_ins ins,2459sljit_s32 dst, sljit_sw dstw,2460sljit_s32 src, sljit_sw srcw)2461{2462sljit_s32 dst_r = FAST_IS_REG(dst) ? dst : TMP_FREG1;24632464if (src & SLJIT_MEM) {2465#if (defined SLJIT_CONFIG_RISCV_32 && SLJIT_CONFIG_RISCV_32)2466FAIL_IF(emit_op_mem2(compiler, WORD_DATA | LOAD_DATA, TMP_REG1, src, srcw, dst, dstw));2467#else /* SLJIT_CONFIG_RISCV_32 */2468FAIL_IF(emit_op_mem2(compiler, ((ins & (1 << 21)) ? WORD_DATA : INT_DATA) | LOAD_DATA, TMP_REG1, src, srcw, dst, dstw));2469#endif /* !SLJIT_CONFIG_RISCV_32 */2470src = TMP_REG1;2471} else if (src == SLJIT_IMM) {2472FAIL_IF(load_immediate(compiler, TMP_REG1, srcw, TMP_REG3));2473src = TMP_REG1;2474}24752476FAIL_IF(push_inst(compiler, ins | FRD(dst_r) | RS1(src)));24772478if (dst & SLJIT_MEM)2479return emit_op_mem2(compiler, DOUBLE_DATA | ((sljit_s32)(~ins >> 24) & 0x2), TMP_FREG1, dst, dstw, 0, 0);2480return SLJIT_SUCCESS;2481}24822483static SLJIT_INLINE sljit_s32 sljit_emit_fop1_conv_f64_from_sw(struct sljit_compiler *compiler, sljit_s32 op,2484sljit_s32 dst, sljit_sw dstw,2485sljit_s32 src, sljit_sw srcw)2486{2487sljit_ins ins = FCVT_S_W | FMT(op);24882489#if (defined SLJIT_CONFIG_RISCV_32 && SLJIT_CONFIG_RISCV_32)2490if (op & SLJIT_32)2491ins |= F3(0x7);2492#else /* !SLJIT_CONFIG_RISCV_32 */2493if (GET_OPCODE(op) == SLJIT_CONV_F64_FROM_SW)2494ins |= (1 << 21);2495else if (src == SLJIT_IMM)2496srcw = (sljit_s32)srcw;24972498if (op != SLJIT_CONV_F64_FROM_S32)2499ins |= F3(0x7);2500#endif /* SLJIT_CONFIG_RISCV_32 */25012502return sljit_emit_fop1_conv_f64_from_w(compiler, ins, dst, dstw, src, srcw);2503}25042505static SLJIT_INLINE sljit_s32 sljit_emit_fop1_conv_f64_from_uw(struct sljit_compiler *compiler, sljit_s32 op,2506sljit_s32 dst, sljit_sw dstw,2507sljit_s32 src, sljit_sw srcw)2508{2509sljit_ins ins = FCVT_S_WU | FMT(op);25102511#if (defined SLJIT_CONFIG_RISCV_32 && SLJIT_CONFIG_RISCV_32)2512if (op & SLJIT_32)2513ins |= F3(0x7);2514#else /* !SLJIT_CONFIG_RISCV_32 */2515if (GET_OPCODE(op) == SLJIT_CONV_F64_FROM_UW)2516ins |= (1 << 21);2517else if (src == SLJIT_IMM)2518srcw = (sljit_u32)srcw;25192520if (op != SLJIT_CONV_F64_FROM_S32)2521ins |= F3(0x7);2522#endif /* SLJIT_CONFIG_RISCV_32 */25232524return sljit_emit_fop1_conv_f64_from_w(compiler, ins, dst, dstw, src, srcw);2525}25262527static SLJIT_INLINE sljit_s32 sljit_emit_fop1_cmp(struct sljit_compiler *compiler, sljit_s32 op,2528sljit_s32 src1, sljit_sw src1w,2529sljit_s32 src2, sljit_sw src2w)2530{2531sljit_ins inst;25322533if (src1 & SLJIT_MEM) {2534FAIL_IF(emit_op_mem2(compiler, FLOAT_DATA(op) | LOAD_DATA, TMP_FREG1, src1, src1w, src2, src2w));2535src1 = TMP_FREG1;2536}25372538if (src2 & SLJIT_MEM) {2539FAIL_IF(emit_op_mem2(compiler, FLOAT_DATA(op) | LOAD_DATA, TMP_FREG2, src2, src2w, 0, 0));2540src2 = TMP_FREG2;2541}25422543switch (GET_FLAG_TYPE(op)) {2544case SLJIT_F_EQUAL:2545case SLJIT_ORDERED_EQUAL:2546inst = FEQ_S | FMT(op) | RD(OTHER_FLAG) | FRS1(src1) | FRS2(src2);2547break;2548case SLJIT_F_LESS:2549case SLJIT_ORDERED_LESS:2550inst = FLT_S | FMT(op) | RD(OTHER_FLAG) | FRS1(src1) | FRS2(src2);2551break;2552case SLJIT_ORDERED_GREATER:2553inst = FLT_S | FMT(op) | RD(OTHER_FLAG) | FRS1(src2) | FRS2(src1);2554break;2555case SLJIT_F_GREATER:2556case SLJIT_UNORDERED_OR_GREATER:2557inst = FLE_S | FMT(op) | RD(OTHER_FLAG) | FRS1(src1) | FRS2(src2);2558break;2559case SLJIT_UNORDERED_OR_LESS:2560inst = FLE_S | FMT(op) | RD(OTHER_FLAG) | FRS1(src2) | FRS2(src1);2561break;2562case SLJIT_UNORDERED_OR_EQUAL:2563FAIL_IF(push_inst(compiler, FLT_S | FMT(op) | RD(OTHER_FLAG) | FRS1(src1) | FRS2(src2)));2564FAIL_IF(push_inst(compiler, FLT_S | FMT(op) | RD(TMP_REG1) | FRS1(src2) | FRS2(src1)));2565inst = OR | RD(OTHER_FLAG) | RS1(OTHER_FLAG) | RS2(TMP_REG1);2566break;2567default: /* SLJIT_UNORDERED */2568if (src1 == src2) {2569inst = FEQ_S | FMT(op) | RD(OTHER_FLAG) | FRS1(src1) | FRS2(src1);2570break;2571}2572FAIL_IF(push_inst(compiler, FEQ_S | FMT(op) | RD(OTHER_FLAG) | FRS1(src1) | FRS2(src1)));2573FAIL_IF(push_inst(compiler, FEQ_S | FMT(op) | RD(TMP_REG1) | FRS1(src2) | FRS2(src2)));2574inst = AND | RD(OTHER_FLAG) | RS1(OTHER_FLAG) | RS2(TMP_REG1);2575break;2576}25772578return push_inst(compiler, inst);2579}25802581SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fop1(struct sljit_compiler *compiler, sljit_s32 op,2582sljit_s32 dst, sljit_sw dstw,2583sljit_s32 src, sljit_sw srcw)2584{2585sljit_s32 dst_r;25862587CHECK_ERROR();2588compiler->cache_arg = 0;2589compiler->cache_argw = 0;25902591SLJIT_COMPILE_ASSERT((SLJIT_32 == 0x100) && !(DOUBLE_DATA & 0x2), float_transfer_bit_error);2592SELECT_FOP1_OPERATION_WITH_CHECKS(compiler, op, dst, dstw, src, srcw);25932594if (GET_OPCODE(op) == SLJIT_CONV_F64_FROM_F32)2595op ^= SLJIT_32;25962597dst_r = FAST_IS_REG(dst) ? dst : TMP_FREG1;25982599if (src & SLJIT_MEM) {2600FAIL_IF(emit_op_mem2(compiler, FLOAT_DATA(op) | LOAD_DATA, dst_r, src, srcw, dst, dstw));2601src = dst_r;2602}26032604switch (GET_OPCODE(op)) {2605case SLJIT_MOV_F64:2606if (src != dst_r) {2607if (!(dst & SLJIT_MEM))2608FAIL_IF(push_inst(compiler, FSGNJ_S | FMT(op) | FRD(dst_r) | FRS1(src) | FRS2(src)));2609else2610dst_r = src;2611}2612break;2613case SLJIT_NEG_F64:2614FAIL_IF(push_inst(compiler, FSGNJN_S | FMT(op) | FRD(dst_r) | FRS1(src) | FRS2(src)));2615break;2616case SLJIT_ABS_F64:2617FAIL_IF(push_inst(compiler, FSGNJX_S | FMT(op) | FRD(dst_r) | FRS1(src) | FRS2(src)));2618break;2619case SLJIT_CONV_F64_FROM_F32:2620/* The SLJIT_32 bit is inverted because sljit_f32 needs to be loaded from the memory. */2621FAIL_IF(push_inst(compiler, FCVT_S_D | ((op & SLJIT_32) ? (1 << 25) : ((1 << 20) | F3(7))) | FRD(dst_r) | FRS1(src)));2622op ^= SLJIT_32;2623break;2624}26252626if (dst & SLJIT_MEM)2627return emit_op_mem2(compiler, FLOAT_DATA(op), dst_r, dst, dstw, 0, 0);2628return SLJIT_SUCCESS;2629}26302631SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fop2(struct sljit_compiler *compiler, sljit_s32 op,2632sljit_s32 dst, sljit_sw dstw,2633sljit_s32 src1, sljit_sw src1w,2634sljit_s32 src2, sljit_sw src2w)2635{2636sljit_s32 dst_r, flags = 0;26372638CHECK_ERROR();2639CHECK(check_sljit_emit_fop2(compiler, op, dst, dstw, src1, src1w, src2, src2w));2640ADJUST_LOCAL_OFFSET(dst, dstw);2641ADJUST_LOCAL_OFFSET(src1, src1w);2642ADJUST_LOCAL_OFFSET(src2, src2w);26432644compiler->cache_arg = 0;2645compiler->cache_argw = 0;26462647dst_r = FAST_IS_REG(dst) ? dst : TMP_FREG2;26482649if (src1 & SLJIT_MEM) {2650if (getput_arg_fast(compiler, FLOAT_DATA(op) | LOAD_DATA, TMP_FREG1, src1, src1w)) {2651FAIL_IF(compiler->error);2652src1 = TMP_FREG1;2653} else2654flags |= SLOW_SRC1;2655}26562657if (src2 & SLJIT_MEM) {2658if (getput_arg_fast(compiler, FLOAT_DATA(op) | LOAD_DATA, TMP_FREG2, src2, src2w)) {2659FAIL_IF(compiler->error);2660src2 = TMP_FREG2;2661} else2662flags |= SLOW_SRC2;2663}26642665if ((flags & (SLOW_SRC1 | SLOW_SRC2)) == (SLOW_SRC1 | SLOW_SRC2)) {2666if ((dst & SLJIT_MEM) && !can_cache(src1, src1w, src2, src2w) && can_cache(src1, src1w, dst, dstw)) {2667FAIL_IF(getput_arg(compiler, FLOAT_DATA(op) | LOAD_DATA, TMP_FREG2, src2, src2w, src1, src1w));2668FAIL_IF(getput_arg(compiler, FLOAT_DATA(op) | LOAD_DATA, TMP_FREG1, src1, src1w, dst, dstw));2669} else {2670FAIL_IF(getput_arg(compiler, FLOAT_DATA(op) | LOAD_DATA, TMP_FREG1, src1, src1w, src2, src2w));2671FAIL_IF(getput_arg(compiler, FLOAT_DATA(op) | LOAD_DATA, TMP_FREG2, src2, src2w, dst, dstw));2672}2673}2674else if (flags & SLOW_SRC1)2675FAIL_IF(getput_arg(compiler, FLOAT_DATA(op) | LOAD_DATA, TMP_FREG1, src1, src1w, dst, dstw));2676else if (flags & SLOW_SRC2)2677FAIL_IF(getput_arg(compiler, FLOAT_DATA(op) | LOAD_DATA, TMP_FREG2, src2, src2w, dst, dstw));26782679if (flags & SLOW_SRC1)2680src1 = TMP_FREG1;2681if (flags & SLOW_SRC2)2682src2 = TMP_FREG2;26832684switch (GET_OPCODE(op)) {2685case SLJIT_ADD_F64:2686FAIL_IF(push_inst(compiler, FADD_S | FMT(op) | FRD(dst_r) | FRS1(src1) | FRS2(src2)));2687break;26882689case SLJIT_SUB_F64:2690FAIL_IF(push_inst(compiler, FSUB_S | FMT(op) | FRD(dst_r) | FRS1(src1) | FRS2(src2)));2691break;26922693case SLJIT_MUL_F64:2694FAIL_IF(push_inst(compiler, FMUL_S | FMT(op) | FRD(dst_r) | FRS1(src1) | FRS2(src2)));2695break;26962697case SLJIT_DIV_F64:2698FAIL_IF(push_inst(compiler, FDIV_S | FMT(op) | FRD(dst_r) | FRS1(src1) | FRS2(src2)));2699break;27002701case SLJIT_COPYSIGN_F64:2702return push_inst(compiler, FSGNJ_S | FMT(op) | FRD(dst_r) | FRS1(src1) | FRS2(src2));2703}27042705if (dst_r != dst)2706FAIL_IF(emit_op_mem2(compiler, FLOAT_DATA(op), TMP_FREG2, dst, dstw, 0, 0));27072708return SLJIT_SUCCESS;2709}27102711SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fset32(struct sljit_compiler *compiler,2712sljit_s32 freg, sljit_f32 value)2713{2714union {2715sljit_s32 imm;2716sljit_f32 value;2717} u;27182719CHECK_ERROR();2720CHECK(check_sljit_emit_fset32(compiler, freg, value));27212722u.value = value;27232724if (u.imm == 0)2725return push_inst(compiler, FMV_W_X | RS1(TMP_ZERO) | FRD(freg));27262727FAIL_IF(load_immediate(compiler, TMP_REG1, u.imm, TMP_REG3));2728return push_inst(compiler, FMV_W_X | RS1(TMP_REG1) | FRD(freg));2729}27302731/* --------------------------------------------------------------------- */2732/* Conditional instructions */2733/* --------------------------------------------------------------------- */27342735SLJIT_API_FUNC_ATTRIBUTE struct sljit_label* sljit_emit_label(struct sljit_compiler *compiler)2736{2737struct sljit_label *label;27382739CHECK_ERROR_PTR();2740CHECK_PTR(check_sljit_emit_label(compiler));27412742if (compiler->last_label && compiler->last_label->size == compiler->size)2743return compiler->last_label;27442745label = (struct sljit_label*)ensure_abuf(compiler, sizeof(struct sljit_label));2746PTR_FAIL_IF(!label);2747set_label(label, compiler);2748return label;2749}27502751#if (defined SLJIT_CONFIG_RISCV_32 && SLJIT_CONFIG_RISCV_32)2752#define BRANCH_LENGTH ((sljit_ins)(3 * sizeof(sljit_ins)) << 7)2753#else /* !SLJIT_CONFIG_RISCV_32 */2754#define BRANCH_LENGTH ((sljit_ins)(7 * sizeof(sljit_ins)) << 7)2755#endif /* SLJIT_CONFIG_RISCV_32 */27562757static sljit_ins get_jump_instruction(sljit_s32 type)2758{2759switch (type) {2760case SLJIT_EQUAL:2761return BNE | RS1(EQUAL_FLAG) | RS2(TMP_ZERO);2762case SLJIT_NOT_EQUAL:2763return BEQ | RS1(EQUAL_FLAG) | RS2(TMP_ZERO);2764case SLJIT_LESS:2765case SLJIT_GREATER:2766case SLJIT_SIG_LESS:2767case SLJIT_SIG_GREATER:2768case SLJIT_OVERFLOW:2769case SLJIT_CARRY:2770case SLJIT_ATOMIC_NOT_STORED:2771case SLJIT_F_EQUAL:2772case SLJIT_ORDERED_EQUAL:2773case SLJIT_ORDERED_NOT_EQUAL:2774case SLJIT_F_LESS:2775case SLJIT_ORDERED_LESS:2776case SLJIT_ORDERED_GREATER:2777case SLJIT_F_LESS_EQUAL:2778case SLJIT_ORDERED_LESS_EQUAL:2779case SLJIT_ORDERED_GREATER_EQUAL:2780case SLJIT_ORDERED:2781return BEQ | RS1(OTHER_FLAG) | RS2(TMP_ZERO);2782break;2783case SLJIT_GREATER_EQUAL:2784case SLJIT_LESS_EQUAL:2785case SLJIT_SIG_GREATER_EQUAL:2786case SLJIT_SIG_LESS_EQUAL:2787case SLJIT_NOT_OVERFLOW:2788case SLJIT_NOT_CARRY:2789case SLJIT_ATOMIC_STORED:2790case SLJIT_F_NOT_EQUAL:2791case SLJIT_UNORDERED_OR_NOT_EQUAL:2792case SLJIT_UNORDERED_OR_EQUAL:2793case SLJIT_F_GREATER_EQUAL:2794case SLJIT_UNORDERED_OR_GREATER_EQUAL:2795case SLJIT_UNORDERED_OR_LESS_EQUAL:2796case SLJIT_F_GREATER:2797case SLJIT_UNORDERED_OR_GREATER:2798case SLJIT_UNORDERED_OR_LESS:2799case SLJIT_UNORDERED:2800return BNE | RS1(OTHER_FLAG) | RS2(TMP_ZERO);2801default:2802/* Not conditional branch. */2803return 0;2804}2805}28062807SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_jump(struct sljit_compiler *compiler, sljit_s32 type)2808{2809struct sljit_jump *jump;2810sljit_ins inst;28112812CHECK_ERROR_PTR();2813CHECK_PTR(check_sljit_emit_jump(compiler, type));28142815jump = (struct sljit_jump*)ensure_abuf(compiler, sizeof(struct sljit_jump));2816PTR_FAIL_IF(!jump);2817set_jump(jump, compiler, type & SLJIT_REWRITABLE_JUMP);2818type &= 0xff;28192820inst = get_jump_instruction(type);28212822if (inst != 0) {2823PTR_FAIL_IF(push_inst(compiler, inst | BRANCH_LENGTH));2824jump->flags |= IS_COND;2825}28262827jump->addr = compiler->size;2828inst = JALR | RS1(TMP_REG1) | IMM_I(0);28292830if (type >= SLJIT_FAST_CALL) {2831jump->flags |= IS_CALL;2832inst |= RD(RETURN_ADDR_REG);2833}28342835PTR_FAIL_IF(push_inst(compiler, inst));28362837/* Maximum number of instructions required for generating a constant. */2838compiler->size += JUMP_MAX_SIZE - 1;2839return jump;2840}28412842SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_call(struct sljit_compiler *compiler, sljit_s32 type,2843sljit_s32 arg_types)2844{2845SLJIT_UNUSED_ARG(arg_types);2846CHECK_ERROR_PTR();2847CHECK_PTR(check_sljit_emit_call(compiler, type, arg_types));28482849if (type & SLJIT_CALL_RETURN) {2850PTR_FAIL_IF(emit_stack_frame_release(compiler, 0));2851type = SLJIT_JUMP | (type & SLJIT_REWRITABLE_JUMP);2852}28532854SLJIT_SKIP_CHECKS(compiler);2855return sljit_emit_jump(compiler, type);2856}28572858SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_cmp(struct sljit_compiler *compiler, sljit_s32 type,2859sljit_s32 src1, sljit_sw src1w,2860sljit_s32 src2, sljit_sw src2w)2861{2862struct sljit_jump *jump;2863sljit_s32 flags;2864sljit_ins inst;2865sljit_s32 src2_tmp_reg = FAST_IS_REG(src1) ? TMP_REG1 : TMP_REG2;28662867CHECK_ERROR_PTR();2868CHECK_PTR(check_sljit_emit_cmp(compiler, type, src1, src1w, src2, src2w));2869ADJUST_LOCAL_OFFSET(src1, src1w);2870ADJUST_LOCAL_OFFSET(src2, src2w);28712872compiler->cache_arg = 0;2873compiler->cache_argw = 0;2874#if (defined SLJIT_CONFIG_RISCV_32 && SLJIT_CONFIG_RISCV_32)2875flags = WORD_DATA | LOAD_DATA;2876#else /* !SLJIT_CONFIG_RISCV_32 */2877flags = ((type & SLJIT_32) ? INT_DATA : WORD_DATA) | LOAD_DATA;2878#endif /* SLJIT_CONFIG_RISCV_32 */28792880if (src1 & SLJIT_MEM) {2881PTR_FAIL_IF(emit_op_mem2(compiler, flags, TMP_REG1, src1, src1w, src2, src2w));2882src1 = TMP_REG1;2883}28842885if (src2 & SLJIT_MEM) {2886PTR_FAIL_IF(emit_op_mem2(compiler, flags | (src1 == TMP_REG1 ? MEM_USE_TMP2 : 0), src2_tmp_reg, src2, src2w, 0, 0));2887src2 = src2_tmp_reg;2888}28892890if (src1 == SLJIT_IMM) {2891if (src1w != 0) {2892PTR_FAIL_IF(load_immediate(compiler, TMP_REG1, src1w, TMP_REG3));2893src1 = TMP_REG1;2894}2895else2896src1 = TMP_ZERO;2897}28982899if (src2 == SLJIT_IMM) {2900if (src2w != 0) {2901PTR_FAIL_IF(load_immediate(compiler, src2_tmp_reg, src2w, TMP_REG3));2902src2 = src2_tmp_reg;2903}2904else2905src2 = TMP_ZERO;2906}29072908jump = (struct sljit_jump*)ensure_abuf(compiler, sizeof(struct sljit_jump));2909PTR_FAIL_IF(!jump);2910set_jump(jump, compiler, (sljit_u32)((type & SLJIT_REWRITABLE_JUMP) | IS_COND));2911type &= 0xff;29122913switch (type) {2914case SLJIT_EQUAL:2915inst = BNE | RS1(src1) | RS2(src2) | BRANCH_LENGTH;2916break;2917case SLJIT_NOT_EQUAL:2918inst = BEQ | RS1(src1) | RS2(src2) | BRANCH_LENGTH;2919break;2920case SLJIT_LESS:2921inst = BGEU | RS1(src1) | RS2(src2) | BRANCH_LENGTH;2922break;2923case SLJIT_GREATER_EQUAL:2924inst = BLTU | RS1(src1) | RS2(src2) | BRANCH_LENGTH;2925break;2926case SLJIT_GREATER:2927inst = BGEU | RS1(src2) | RS2(src1) | BRANCH_LENGTH;2928break;2929case SLJIT_LESS_EQUAL:2930inst = BLTU | RS1(src2) | RS2(src1) | BRANCH_LENGTH;2931break;2932case SLJIT_SIG_LESS:2933inst = BGE | RS1(src1) | RS2(src2) | BRANCH_LENGTH;2934break;2935case SLJIT_SIG_GREATER_EQUAL:2936inst = BLT | RS1(src1) | RS2(src2) | BRANCH_LENGTH;2937break;2938case SLJIT_SIG_GREATER:2939inst = BGE | RS1(src2) | RS2(src1) | BRANCH_LENGTH;2940break;2941case SLJIT_SIG_LESS_EQUAL:2942inst = BLT | RS1(src2) | RS2(src1) | BRANCH_LENGTH;2943break;2944}29452946PTR_FAIL_IF(push_inst(compiler, inst));29472948jump->addr = compiler->size;2949PTR_FAIL_IF(push_inst(compiler, JALR | RD(TMP_ZERO) | RS1(TMP_REG1) | IMM_I(0)));29502951/* Maximum number of instructions required for generating a constant. */2952compiler->size += JUMP_MAX_SIZE - 1;2953return jump;2954}29552956#undef BRANCH_LENGTH29572958SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_ijump(struct sljit_compiler *compiler, sljit_s32 type, sljit_s32 src, sljit_sw srcw)2959{2960struct sljit_jump *jump;29612962CHECK_ERROR();2963CHECK(check_sljit_emit_ijump(compiler, type, src, srcw));29642965if (src != SLJIT_IMM) {2966if (src & SLJIT_MEM) {2967ADJUST_LOCAL_OFFSET(src, srcw);2968FAIL_IF(emit_op_mem(compiler, WORD_DATA | LOAD_DATA, TMP_REG1, src, srcw));2969src = TMP_REG1;2970}2971return push_inst(compiler, JALR | RD((type >= SLJIT_FAST_CALL) ? RETURN_ADDR_REG : TMP_ZERO) | RS1(src) | IMM_I(0));2972}29732974/* These jumps are converted to jump/call instructions when possible. */2975jump = (struct sljit_jump*)ensure_abuf(compiler, sizeof(struct sljit_jump));2976FAIL_IF(!jump);2977set_jump(jump, compiler, JUMP_ADDR | ((type >= SLJIT_FAST_CALL) ? IS_CALL : 0));2978jump->u.target = (sljit_uw)srcw;29792980jump->addr = compiler->size;2981FAIL_IF(push_inst(compiler, JALR | RD((type >= SLJIT_FAST_CALL) ? RETURN_ADDR_REG : TMP_ZERO) | RS1(TMP_REG1) | IMM_I(0)));29822983/* Maximum number of instructions required for generating a constant. */2984compiler->size += JUMP_MAX_SIZE - 1;2985return SLJIT_SUCCESS;2986}29872988SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_icall(struct sljit_compiler *compiler, sljit_s32 type,2989sljit_s32 arg_types,2990sljit_s32 src, sljit_sw srcw)2991{2992SLJIT_UNUSED_ARG(arg_types);2993CHECK_ERROR();2994CHECK(check_sljit_emit_icall(compiler, type, arg_types, src, srcw));29952996if (src & SLJIT_MEM) {2997ADJUST_LOCAL_OFFSET(src, srcw);2998FAIL_IF(emit_op_mem(compiler, WORD_DATA | LOAD_DATA, TMP_REG1, src, srcw));2999src = TMP_REG1;3000}30013002if (type & SLJIT_CALL_RETURN) {3003if (src >= SLJIT_FIRST_SAVED_REG && src <= (SLJIT_S0 - SLJIT_KEPT_SAVEDS_COUNT(compiler->options))) {3004FAIL_IF(push_inst(compiler, ADDI | RD(TMP_REG1) | RS1(src) | IMM_I(0)));3005src = TMP_REG1;3006}30073008FAIL_IF(emit_stack_frame_release(compiler, 0));3009type = SLJIT_JUMP;3010}30113012SLJIT_SKIP_CHECKS(compiler);3013return sljit_emit_ijump(compiler, type, src, srcw);3014}30153016SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_flags(struct sljit_compiler *compiler, sljit_s32 op,3017sljit_s32 dst, sljit_sw dstw,3018sljit_s32 type)3019{3020sljit_s32 src_r, dst_r, invert;3021sljit_s32 saved_op = op;3022#if (defined SLJIT_CONFIG_RISCV_32 && SLJIT_CONFIG_RISCV_32)3023sljit_s32 mem_type = WORD_DATA;3024#else /* !SLJIT_CONFIG_RISCV_32 */3025sljit_s32 mem_type = ((op & SLJIT_32) || op == SLJIT_MOV32) ? (INT_DATA | SIGNED_DATA) : WORD_DATA;3026#endif /* SLJIT_CONFIG_RISCV_32 */30273028CHECK_ERROR();3029CHECK(check_sljit_emit_op_flags(compiler, op, dst, dstw, type));3030ADJUST_LOCAL_OFFSET(dst, dstw);30313032op = GET_OPCODE(op);3033dst_r = (op < SLJIT_ADD && FAST_IS_REG(dst)) ? dst : TMP_REG2;30343035compiler->cache_arg = 0;3036compiler->cache_argw = 0;30373038if (op >= SLJIT_ADD && (dst & SLJIT_MEM))3039FAIL_IF(emit_op_mem2(compiler, mem_type | LOAD_DATA, TMP_REG1, dst, dstw, dst, dstw));30403041if (type < SLJIT_F_EQUAL) {3042src_r = OTHER_FLAG;3043invert = type & 0x1;30443045switch (type) {3046case SLJIT_EQUAL:3047case SLJIT_NOT_EQUAL:3048FAIL_IF(push_inst(compiler, SLTUI | RD(dst_r) | RS1(EQUAL_FLAG) | IMM_I(1)));3049src_r = dst_r;3050break;3051case SLJIT_OVERFLOW:3052case SLJIT_NOT_OVERFLOW:3053if (compiler->status_flags_state & (SLJIT_CURRENT_FLAGS_ADD | SLJIT_CURRENT_FLAGS_SUB)) {3054src_r = OTHER_FLAG;3055break;3056}3057FAIL_IF(push_inst(compiler, SLTUI | RD(dst_r) | RS1(OTHER_FLAG) | IMM_I(1)));3058src_r = dst_r;3059invert ^= 0x1;3060break;3061case SLJIT_ATOMIC_STORED:3062case SLJIT_ATOMIC_NOT_STORED:3063invert ^= 0x1;3064break;3065}3066} else {3067invert = 0;3068src_r = OTHER_FLAG;30693070switch (type) {3071case SLJIT_F_NOT_EQUAL:3072case SLJIT_UNORDERED_OR_NOT_EQUAL:3073case SLJIT_UNORDERED_OR_EQUAL: /* Not supported. */3074case SLJIT_F_GREATER_EQUAL:3075case SLJIT_UNORDERED_OR_GREATER_EQUAL:3076case SLJIT_UNORDERED_OR_LESS_EQUAL:3077case SLJIT_F_GREATER:3078case SLJIT_UNORDERED_OR_GREATER:3079case SLJIT_UNORDERED_OR_LESS:3080case SLJIT_UNORDERED:3081invert = 1;3082break;3083}3084}30853086if (invert) {3087FAIL_IF(push_inst(compiler, XORI | RD(dst_r) | RS1(src_r) | IMM_I(1)));3088src_r = dst_r;3089}30903091if (op < SLJIT_ADD) {3092if (dst & SLJIT_MEM)3093return emit_op_mem(compiler, mem_type, src_r, dst, dstw);30943095if (src_r != dst_r)3096return push_inst(compiler, ADDI | RD(dst_r) | RS1(src_r) | IMM_I(0));3097return SLJIT_SUCCESS;3098}30993100mem_type |= CUMULATIVE_OP | IMM_OP | ALT_KEEP_CACHE;31013102if (dst & SLJIT_MEM)3103return emit_op(compiler, saved_op, mem_type, dst, dstw, TMP_REG1, 0, src_r, 0);3104return emit_op(compiler, saved_op, mem_type, dst, dstw, dst, dstw, src_r, 0);3105}31063107SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_select(struct sljit_compiler *compiler, sljit_s32 type,3108sljit_s32 dst_reg,3109sljit_s32 src1, sljit_sw src1w,3110sljit_s32 src2_reg)3111{3112sljit_ins *ptr;3113sljit_uw size;3114#if (defined SLJIT_CONFIG_RISCV_64 && SLJIT_CONFIG_RISCV_64)3115sljit_ins word = (sljit_ins)(type & SLJIT_32) >> 5;3116sljit_s32 inp_flags = ((type & SLJIT_32) ? INT_DATA : WORD_DATA) | LOAD_DATA;3117#else /* !SLJIT_CONFIG_RISCV_64 */3118sljit_s32 inp_flags = WORD_DATA | LOAD_DATA;3119#endif /* SLJIT_CONFIG_RISCV_64 */31203121SLJIT_ASSERT(WORD == 0 || WORD == 0x8);31223123CHECK_ERROR();3124CHECK(check_sljit_emit_select(compiler, type, dst_reg, src1, src1w, src2_reg));31253126ADJUST_LOCAL_OFFSET(src1, src1w);31273128if (dst_reg != src2_reg) {3129if (dst_reg == src1) {3130src1 = src2_reg;3131src1w = 0;3132type ^= 0x1;3133} else {3134if (ADDRESSING_DEPENDS_ON(src1, dst_reg)) {3135FAIL_IF(push_inst(compiler, ADDI | RD(TMP_REG1) | RS1(dst_reg) | IMM_I(0)));31363137if ((src1 & REG_MASK) == dst_reg)3138src1 = (src1 & ~REG_MASK) | TMP_REG1;31393140if (OFFS_REG(src1) == dst_reg)3141src1 = (src1 & ~OFFS_REG_MASK) | TO_OFFS_REG(TMP_REG1);3142}31433144FAIL_IF(push_inst(compiler, ADDI | WORD | RD(dst_reg) | RS1(src2_reg) | IMM_I(0)));3145}3146}31473148size = compiler->size;31493150ptr = (sljit_ins*)ensure_buf(compiler, sizeof(sljit_ins));3151FAIL_IF(!ptr);3152compiler->size++;31533154if (src1 & SLJIT_MEM) {3155FAIL_IF(emit_op_mem(compiler, inp_flags, dst_reg, src1, src1w));3156} else if (src1 == SLJIT_IMM) {3157#if (defined SLJIT_CONFIG_RISCV_64 && SLJIT_CONFIG_RISCV_64)3158if (word)3159src1w = (sljit_s32)src1w;3160#endif /* SLJIT_CONFIG_RISCV_64 */3161FAIL_IF(load_immediate(compiler, dst_reg, src1w, TMP_REG1));3162} else3163FAIL_IF(push_inst(compiler, ADDI | WORD | RD(dst_reg) | RS1(src1) | IMM_I(0)));31643165size = compiler->size - size;3166*ptr = get_jump_instruction(type & ~SLJIT_32) | (sljit_ins)((size & 0x7) << 9) | (sljit_ins)((size >> 3) << 25);3167return SLJIT_SUCCESS;3168}31693170#undef WORD31713172SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fselect(struct sljit_compiler *compiler, sljit_s32 type,3173sljit_s32 dst_freg,3174sljit_s32 src1, sljit_sw src1w,3175sljit_s32 src2_freg)3176{3177sljit_ins *ptr;3178sljit_uw size;31793180CHECK_ERROR();3181CHECK(check_sljit_emit_fselect(compiler, type, dst_freg, src1, src1w, src2_freg));31823183ADJUST_LOCAL_OFFSET(src1, src1w);31843185if (dst_freg != src2_freg) {3186if (dst_freg == src1) {3187src1 = src2_freg;3188src1w = 0;3189type ^= 0x1;3190} else3191FAIL_IF(push_inst(compiler, FSGNJ_S | FMT(type) | FRD(dst_freg) | FRS1(src2_freg) | FRS2(src2_freg)));3192}31933194size = compiler->size;31953196ptr = (sljit_ins*)ensure_buf(compiler, sizeof(sljit_ins));3197FAIL_IF(!ptr);3198compiler->size++;31993200if (src1 & SLJIT_MEM)3201FAIL_IF(emit_op_mem(compiler, FLOAT_DATA(type) | LOAD_DATA, dst_freg, src1, src1w));3202else3203FAIL_IF(push_inst(compiler, FSGNJ_S | FMT(type) | FRD(dst_freg) | FRS1(src1) | FRS2(src1)));32043205size = compiler->size - size;3206*ptr = get_jump_instruction(type & ~SLJIT_32) | (sljit_ins)((size & 0x7) << 9) | (sljit_ins)((size >> 3) << 25);3207return SLJIT_SUCCESS;3208}32093210#undef FLOAT_DATA3211#undef FMT32123213SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_mem(struct sljit_compiler *compiler, sljit_s32 type,3214sljit_s32 reg,3215sljit_s32 mem, sljit_sw memw)3216{3217sljit_s32 flags;32183219CHECK_ERROR();3220CHECK(check_sljit_emit_mem(compiler, type, reg, mem, memw));32213222if (!(reg & REG_PAIR_MASK))3223return sljit_emit_mem_unaligned(compiler, type, reg, mem, memw);32243225if (SLJIT_UNLIKELY(mem & OFFS_REG_MASK)) {3226memw &= 0x3;32273228if (SLJIT_UNLIKELY(memw != 0)) {3229FAIL_IF(push_inst(compiler, SLLI | RD(TMP_REG1) | RS1(OFFS_REG(mem)) | IMM_I(memw)));3230FAIL_IF(push_inst(compiler, ADD | RD(TMP_REG1) | RS1(TMP_REG1) | RS2(mem & REG_MASK)));3231} else3232FAIL_IF(push_inst(compiler, ADD | RD(TMP_REG1) | RS1(mem & REG_MASK) | RS2(OFFS_REG(mem))));32333234mem = TMP_REG1;3235memw = 0;3236} else if (memw > SIMM_MAX - SSIZE_OF(sw) || memw < SIMM_MIN) {3237if (((memw + 0x800) & 0xfff) <= 0xfff - SSIZE_OF(sw)) {3238FAIL_IF(load_immediate(compiler, TMP_REG1, TO_ARGW_HI(memw), TMP_REG3));3239memw &= 0xfff;3240} else {3241FAIL_IF(load_immediate(compiler, TMP_REG1, memw, TMP_REG3));3242memw = 0;3243}32443245if (mem & REG_MASK)3246FAIL_IF(push_inst(compiler, ADD | RD(TMP_REG1) | RS1(TMP_REG1) | RS2(mem & REG_MASK)));32473248mem = TMP_REG1;3249} else {3250mem &= REG_MASK;3251memw &= 0xfff;3252}32533254SLJIT_ASSERT((memw >= 0 && memw <= SIMM_MAX - SSIZE_OF(sw)) || (memw > SIMM_MAX && memw <= 0xfff));32553256if (!(type & SLJIT_MEM_STORE) && mem == REG_PAIR_FIRST(reg)) {3257FAIL_IF(push_mem_inst(compiler, WORD_DATA | LOAD_DATA, REG_PAIR_SECOND(reg), mem, (memw + SSIZE_OF(sw)) & 0xfff));3258return push_mem_inst(compiler, WORD_DATA | LOAD_DATA, REG_PAIR_FIRST(reg), mem, memw);3259}32603261flags = WORD_DATA | (!(type & SLJIT_MEM_STORE) ? LOAD_DATA : 0);32623263FAIL_IF(push_mem_inst(compiler, flags, REG_PAIR_FIRST(reg), mem, memw));3264return push_mem_inst(compiler, flags, REG_PAIR_SECOND(reg), mem, (memw + SSIZE_OF(sw)) & 0xfff);3265}32663267#undef TO_ARGW_HI32683269SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_atomic_load(struct sljit_compiler *compiler, sljit_s32 op,3270sljit_s32 dst_reg,3271sljit_s32 mem_reg)3272{3273sljit_ins ins;32743275CHECK_ERROR();3276CHECK(check_sljit_emit_atomic_load(compiler, op, dst_reg, mem_reg));32773278if (op & SLJIT_ATOMIC_USE_CAS)3279return SLJIT_ERR_UNSUPPORTED;32803281switch (GET_OPCODE(op)) {3282case SLJIT_MOV:3283case SLJIT_MOV_P:3284#if (defined SLJIT_CONFIG_RISCV_64 && SLJIT_CONFIG_RISCV_64)3285ins = LR | (3 << 12);3286break;3287#endif /* SLJIT_CONFIG_RISCV_64 */3288case SLJIT_MOV_S32:3289case SLJIT_MOV32:3290ins = LR | (2 << 12);3291break;32923293default:3294return SLJIT_ERR_UNSUPPORTED;3295}32963297if (op & SLJIT_ATOMIC_TEST)3298return SLJIT_SUCCESS;32993300return push_inst(compiler, ins | RD(dst_reg) | RS1(mem_reg));3301}33023303SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_atomic_store(struct sljit_compiler *compiler, sljit_s32 op,3304sljit_s32 src_reg,3305sljit_s32 mem_reg,3306sljit_s32 temp_reg)3307{3308sljit_ins ins;33093310/* temp_reg == mem_reg is undefined so use another temp register */3311SLJIT_UNUSED_ARG(temp_reg);33123313CHECK_ERROR();3314CHECK(check_sljit_emit_atomic_store(compiler, op, src_reg, mem_reg, temp_reg));33153316if (op & SLJIT_ATOMIC_USE_CAS)3317return SLJIT_ERR_UNSUPPORTED;33183319switch (GET_OPCODE(op)) {3320case SLJIT_MOV:3321case SLJIT_MOV_P:3322#if (defined SLJIT_CONFIG_RISCV_64 && SLJIT_CONFIG_RISCV_64)3323ins = SC | (3 << 12);3324break;3325#endif /* SLJIT_CONFIG_RISCV_64 */3326case SLJIT_MOV_S32:3327case SLJIT_MOV32:3328ins = SC | (2 << 12);3329break;33303331default:3332return SLJIT_ERR_UNSUPPORTED;3333}33343335if (op & SLJIT_ATOMIC_TEST)3336return SLJIT_SUCCESS;33373338return push_inst(compiler, ins | RD(OTHER_FLAG) | RS1(mem_reg) | RS2(src_reg));3339}33403341/*3342SEW = Selected element width3343LMUL = Vector register group multiplier33443345VLMUL values (in binary):3346100 : reserved3347101 : 1/83348110 : 1/43349111 : 1/23350000 : 13351001 : 23352010 : 43353011 : 83354*/33553356static SLJIT_INLINE sljit_s32 sljit_emit_vsetivli(struct sljit_compiler *compiler, sljit_s32 type, sljit_ins vlmul)3357{3358sljit_ins elem_size = (sljit_ins)SLJIT_SIMD_GET_ELEM_SIZE(type);3359sljit_ins avl = (sljit_ins)1 << (SLJIT_SIMD_GET_REG_SIZE(type) - elem_size);33603361return push_inst(compiler, VSETIVLI | RD(TMP_REG1) | (elem_size << 23) | (vlmul << 20) | (avl << 15));3362}33633364static SLJIT_INLINE sljit_s32 sljit_emit_vsetivli_size(struct sljit_compiler *compiler, sljit_s32 reg_size, sljit_s32 elem_size)3365{3366sljit_ins avl = (sljit_ins)1 << (reg_size - elem_size);3367return push_inst(compiler, VSETIVLI | RD(TMP_REG1) | ((sljit_ins)elem_size << 23) | (avl << 15));3368}33693370static sljit_s32 sljit_emit_vmem(struct sljit_compiler *compiler, sljit_ins ins, sljit_s32 elem_size, sljit_s32 mem, sljit_sw memw)3371{3372sljit_s32 base = mem & REG_MASK;33733374if (elem_size > 0)3375ins |= (1 << 14) | ((sljit_ins)elem_size << 12);33763377if (SLJIT_UNLIKELY(mem & OFFS_REG_MASK)) {3378memw &= 0x3;33793380if (SLJIT_UNLIKELY(memw)) {3381FAIL_IF(push_inst(compiler, SLLI | RD(TMP_REG1) | RS1(OFFS_REG(mem)) | IMM_I(memw)));3382}33833384FAIL_IF(push_inst(compiler, ADD | RD(TMP_REG1) | RS1(base) | RS2(!memw ? OFFS_REG(mem) : TMP_REG1)));3385return push_inst(compiler, ins | RS1(TMP_REG1));3386}33873388if (memw == 0)3389return push_inst(compiler, ins | RS1(base));33903391if (memw <= SIMM_MAX && memw >= SIMM_MIN) {3392FAIL_IF(push_inst(compiler, ADDI | RD(TMP_REG1) | RS1(base) | IMM_I(memw)));3393return push_inst(compiler, ins | RS1(TMP_REG1));3394}33953396FAIL_IF(load_immediate(compiler, TMP_REG1, memw, TMP_REG3));33973398if (base != 0)3399FAIL_IF(push_inst(compiler, ADD | RD(TMP_REG1) | RS1(TMP_REG1) | RS2(base)));34003401return push_inst(compiler, ins | RS1(TMP_REG1));3402}34033404SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_simd_mov(struct sljit_compiler *compiler, sljit_s32 type,3405sljit_s32 vreg,3406sljit_s32 srcdst, sljit_sw srcdstw)3407{3408sljit_s32 reg_size = SLJIT_SIMD_GET_REG_SIZE(type);3409sljit_s32 elem_size = SLJIT_SIMD_GET_ELEM_SIZE(type);3410sljit_ins ins;34113412CHECK_ERROR();3413CHECK(check_sljit_emit_simd_mov(compiler, type, vreg, srcdst, srcdstw));34143415ADJUST_LOCAL_OFFSET(srcdst, srcdstw);34163417if (reg_size != 4)3418return SLJIT_ERR_UNSUPPORTED;34193420if (type & SLJIT_SIMD_TEST)3421return SLJIT_SUCCESS;34223423if (elem_size > 3)3424elem_size = 3;34253426FAIL_IF(sljit_emit_vsetivli_size(compiler, reg_size, elem_size));34273428if (srcdst & SLJIT_MEM) {3429ins = (type & SLJIT_SIMD_STORE) ? VS : VL;3430return sljit_emit_vmem(compiler, ins | VRD(vreg), elem_size, srcdst, srcdstw);3431}34323433if (type & SLJIT_SIMD_STORE)3434ins = VRD(srcdst) | VRS1(vreg);3435else3436ins = VRD(vreg) | VRS1(srcdst);34373438return push_inst(compiler, VMV_VV | ins);3439}34403441static sljit_s32 sljit_simd_get_mem_flags(sljit_s32 elem_size)3442{3443switch (elem_size) {3444case 0:3445return BYTE_DATA;3446case 1:3447return HALF_DATA;3448#if (defined SLJIT_CONFIG_RISCV_64 && SLJIT_CONFIG_RISCV_64)3449case 2:3450return INT_DATA;3451#endif /* SLJIT_CONFIG_RISCV_64 */3452default:3453return WORD_DATA;3454}3455}34563457static sljit_sw sljit_simd_get_imm(sljit_s32 elem_size, sljit_sw imm)3458{3459switch (elem_size) {3460case 0:3461return (sljit_s8)imm;3462case 1:3463return (sljit_s16)imm;3464#if (defined SLJIT_CONFIG_RISCV_64 && SLJIT_CONFIG_RISCV_64)3465case 2:3466return (sljit_s32)imm;3467#endif /* SLJIT_CONFIG_RISCV_64 */3468default:3469return imm;3470}3471}34723473SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_simd_replicate(struct sljit_compiler *compiler, sljit_s32 type,3474sljit_s32 vreg,3475sljit_s32 src, sljit_sw srcw)3476{3477sljit_s32 reg_size = SLJIT_SIMD_GET_REG_SIZE(type);3478sljit_s32 elem_size = SLJIT_SIMD_GET_ELEM_SIZE(type);3479sljit_s32 flags;34803481CHECK_ERROR();3482CHECK(check_sljit_emit_simd_replicate(compiler, type, vreg, src, srcw));34833484ADJUST_LOCAL_OFFSET(src, srcw);34853486if (reg_size != 4)3487return SLJIT_ERR_UNSUPPORTED;34883489#if (defined SLJIT_CONFIG_RISCV_32 && SLJIT_CONFIG_RISCV_32)3490if ((type & SLJIT_SIMD_FLOAT) ? (elem_size < 2 || elem_size > 3) : elem_size > 2)3491return SLJIT_ERR_UNSUPPORTED;3492#else /* !SLJIT_CONFIG_RISCV_32 */3493if (((type & SLJIT_SIMD_FLOAT) && elem_size < 2) || elem_size > 3)3494return SLJIT_ERR_UNSUPPORTED;3495#endif /* SLJIT_CONFIG_RISCV_32 */34963497if (type & SLJIT_SIMD_TEST)3498return SLJIT_SUCCESS;34993500FAIL_IF(sljit_emit_vsetivli(compiler, type, 0));35013502if (type & SLJIT_SIMD_FLOAT) {3503if (src == SLJIT_IMM)3504return push_inst(compiler, VMV_VI | VRD(vreg) | ((sljit_ins)(srcw & 0x1f) << 15));35053506if (src & SLJIT_MEM) {3507flags = (elem_size == 2) ? SINGLE_DATA : DOUBLE_DATA;3508FAIL_IF(emit_op_mem(compiler, flags | LOAD_DATA, TMP_FREG1, src, srcw));3509src = TMP_FREG1;3510}35113512return push_inst(compiler, VFMV_VF | VRD(vreg) | FRS1(src));3513}35143515if (src == SLJIT_IMM) {3516srcw = sljit_simd_get_imm(elem_size, srcw);35173518if (srcw >= -0x10 && srcw <= 0xf)3519return push_inst(compiler, VMV_VI | VRD(vreg) | ((sljit_ins)(srcw & 0x1f) << 15));35203521FAIL_IF(load_immediate(compiler, TMP_REG1, srcw, TMP_REG3));3522src = TMP_REG1;3523} else if (src & SLJIT_MEM) {3524FAIL_IF(emit_op_mem(compiler, sljit_simd_get_mem_flags(elem_size) | LOAD_DATA, TMP_REG1, src, srcw));3525src = TMP_REG1;3526}35273528return push_inst(compiler, VMV_VX | VRD(vreg) | RS1(src));3529}35303531SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_simd_lane_mov(struct sljit_compiler *compiler, sljit_s32 type,3532sljit_s32 vreg, sljit_s32 lane_index,3533sljit_s32 srcdst, sljit_sw srcdstw)3534{3535sljit_s32 reg_size = SLJIT_SIMD_GET_REG_SIZE(type);3536sljit_s32 elem_size = SLJIT_SIMD_GET_ELEM_SIZE(type);3537sljit_s32 flags;35383539CHECK_ERROR();3540CHECK(check_sljit_emit_simd_lane_mov(compiler, type, vreg, lane_index, srcdst, srcdstw));35413542ADJUST_LOCAL_OFFSET(srcdst, srcdstw);35433544if (reg_size != 4)3545return SLJIT_ERR_UNSUPPORTED;35463547#if (defined SLJIT_CONFIG_RISCV_32 && SLJIT_CONFIG_RISCV_32)3548if ((type & SLJIT_SIMD_FLOAT) ? (elem_size < 2 || elem_size > 3) : elem_size > 2)3549return SLJIT_ERR_UNSUPPORTED;3550#else /* !SLJIT_CONFIG_RISCV_32 */3551if (((type & SLJIT_SIMD_FLOAT) && elem_size < 2) || elem_size > 3)3552return SLJIT_ERR_UNSUPPORTED;3553#endif /* SLJIT_CONFIG_RISCV_32 */35543555if (type & SLJIT_SIMD_TEST)3556return SLJIT_SUCCESS;35573558if (type & SLJIT_SIMD_STORE) {3559FAIL_IF(push_inst(compiler, VSETIVLI | RD(TMP_REG1) | ((sljit_ins)elem_size << 23) | (1 << 15)));35603561if (lane_index > 0) {3562FAIL_IF(push_inst(compiler, VSLIDEDOWN_VI | VRD(TMP_VREG1) | ((sljit_ins)lane_index << 15) | VRS2(vreg)));3563vreg = TMP_VREG1;3564}35653566if (srcdst & SLJIT_MEM)3567return sljit_emit_vmem(compiler, VS | VRD(vreg), elem_size, srcdst, srcdstw);35683569if (type & SLJIT_SIMD_FLOAT)3570return push_inst(compiler, VFMV_FS | FRD(srcdst) | VRS2(vreg));35713572FAIL_IF(push_inst(compiler, VMV_XS | RD(srcdst) | VRS2(vreg)));35733574#if (defined SLJIT_CONFIG_RISCV_32 && SLJIT_CONFIG_RISCV_32)3575if ((type & SLJIT_SIMD_LANE_SIGNED) || elem_size >= 2)3576return SLJIT_SUCCESS;3577#else /* !SLJIT_CONFIG_RISCV_32 */3578if ((type & SLJIT_SIMD_LANE_SIGNED) || elem_size >= 3 || (elem_size == 2 && (type & SLJIT_32)))3579return SLJIT_SUCCESS;3580#endif /* SLJIT_CONFIG_RISCV_32 */35813582if (elem_size == 0)3583return push_inst(compiler, ANDI | RD(srcdst) | RS1(srcdst) | IMM_I(0xff));35843585#if (defined SLJIT_CONFIG_RISCV_32 && SLJIT_CONFIG_RISCV_32)3586flags = 16;3587#else /* !SLJIT_CONFIG_RISCV_32 */3588flags = (elem_size == 1) ? 48 : 32;3589#endif /* SLJIT_CONFIG_RISCV_32 */35903591FAIL_IF(push_inst(compiler, SLLI | RD(srcdst) | RS1(srcdst) | IMM_I(flags)));3592return push_inst(compiler, SRLI | RD(srcdst) | RS1(srcdst) | IMM_I(flags));3593}35943595if (type & SLJIT_SIMD_LANE_ZERO) {3596FAIL_IF(sljit_emit_vsetivli(compiler, type, 0));3597FAIL_IF(push_inst(compiler, VMV_VI | VRD(vreg)));3598}35993600if (srcdst & SLJIT_MEM) {3601FAIL_IF(push_inst(compiler, VSETIVLI | RD(TMP_REG1) | ((sljit_ins)elem_size << 23) | (1 << 15)));3602FAIL_IF(sljit_emit_vmem(compiler, VL | VRD(lane_index > 0 ? TMP_VREG1 : vreg), elem_size, srcdst, srcdstw));36033604if (lane_index == 0)3605return SLJIT_SUCCESS;36063607FAIL_IF(push_inst(compiler, VSETIVLI | RD(TMP_REG1) | ((sljit_ins)elem_size << 23) | ((sljit_ins)(lane_index + 1) << 15)));3608return push_inst(compiler, VSLIDEUP_VI | VRD(vreg) | ((sljit_ins)lane_index << 15) | VRS2(TMP_VREG1));3609}36103611if (!(type & SLJIT_SIMD_LANE_ZERO) || lane_index > 0)3612FAIL_IF(push_inst(compiler, VSETIVLI | RD(TMP_REG1) | ((sljit_ins)elem_size << 23) | ((sljit_ins)(lane_index + 1) << 15)));36133614if (type & SLJIT_SIMD_FLOAT) {3615FAIL_IF(push_inst(compiler, VFMV_SF | VRD(lane_index > 0 ? TMP_VREG1 : vreg) | FRS1(srcdst)));36163617if (lane_index == 0)3618return SLJIT_SUCCESS;36193620return push_inst(compiler, VSLIDEUP_VI | VRD(vreg) | ((sljit_ins)lane_index << 15) | VRS2(TMP_VREG1));3621}36223623if (srcdst == SLJIT_IMM) {3624srcdstw = sljit_simd_get_imm(elem_size, srcdstw);3625FAIL_IF(load_immediate(compiler, TMP_REG1, srcdstw, TMP_REG3));3626srcdst = TMP_REG1;3627}36283629FAIL_IF(push_inst(compiler, VMV_SX | VRD(lane_index > 0 ? TMP_VREG1 : vreg) | RS1(srcdst)));36303631if (lane_index == 0)3632return SLJIT_SUCCESS;36333634return push_inst(compiler, VSLIDEUP_VI | VRD(vreg) | ((sljit_ins)lane_index << 15) | VRS2(TMP_VREG1));3635}36363637SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_simd_lane_replicate(struct sljit_compiler *compiler, sljit_s32 type,3638sljit_s32 vreg,3639sljit_s32 src, sljit_s32 src_lane_index)3640{3641sljit_s32 reg_size = SLJIT_SIMD_GET_REG_SIZE(type);3642sljit_s32 elem_size = SLJIT_SIMD_GET_ELEM_SIZE(type);36433644CHECK_ERROR();3645CHECK(check_sljit_emit_simd_lane_replicate(compiler, type, vreg, src, src_lane_index));36463647if (reg_size != 4)3648return SLJIT_ERR_UNSUPPORTED;36493650if (((type & SLJIT_SIMD_FLOAT) && elem_size < 2) || elem_size > 3)3651return SLJIT_ERR_UNSUPPORTED;36523653if (type & SLJIT_SIMD_TEST)3654return SLJIT_SUCCESS;36553656FAIL_IF(sljit_emit_vsetivli(compiler, type, 0));36573658FAIL_IF(push_inst(compiler, VRGATHER_VI | VRD(vreg != src ? vreg : TMP_VREG1) | ((sljit_ins)src_lane_index << 15) | VRS2(src)));3659if (vreg == src)3660return push_inst(compiler, VMV_VV | VRD(vreg) | VRS1(TMP_VREG1));3661return SLJIT_SUCCESS;3662}36633664SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_simd_extend(struct sljit_compiler *compiler, sljit_s32 type,3665sljit_s32 vreg,3666sljit_s32 src, sljit_sw srcw)3667{3668sljit_s32 reg_size = SLJIT_SIMD_GET_REG_SIZE(type);3669sljit_s32 elem_size = SLJIT_SIMD_GET_ELEM_SIZE(type);3670sljit_s32 elem2_size = SLJIT_SIMD_GET_ELEM2_SIZE(type);3671sljit_ins ins;36723673CHECK_ERROR();3674CHECK(check_sljit_emit_simd_extend(compiler, type, vreg, src, srcw));36753676ADJUST_LOCAL_OFFSET(src, srcw);36773678if (reg_size != 4)3679return SLJIT_ERR_UNSUPPORTED;36803681#if (defined SLJIT_CONFIG_RISCV_32 && SLJIT_CONFIG_RISCV_32)3682if ((type & SLJIT_SIMD_FLOAT) ? (elem_size < 2 || elem_size > 3) : elem_size > 2)3683return SLJIT_ERR_UNSUPPORTED;3684#else /* !SLJIT_CONFIG_RISCV_32 */3685if (((type & SLJIT_SIMD_FLOAT) && elem_size < 2) || elem_size > 3)3686return SLJIT_ERR_UNSUPPORTED;3687#endif /* SLJIT_CONFIG_RISCV_32 */36883689if (type & SLJIT_SIMD_TEST)3690return SLJIT_SUCCESS;36913692if ((src & SLJIT_MEM) || vreg == src) {3693ins = (sljit_ins)1 << (reg_size - elem2_size);3694FAIL_IF(push_inst(compiler, VSETIVLI | RD(TMP_REG1) | ((sljit_ins)elem_size << 23) | (ins << 15)));36953696if (src & SLJIT_MEM)3697FAIL_IF(sljit_emit_vmem(compiler, VL | VRD(TMP_VREG1), elem_size, src, srcw));3698else3699FAIL_IF(push_inst(compiler, VMV_VV | VRD(TMP_VREG1) | VRS1(src)));37003701src = TMP_VREG1;3702}37033704if (type & SLJIT_SIMD_FLOAT) {3705FAIL_IF(sljit_emit_vsetivli(compiler, type, 0x7));3706return push_inst(compiler, VFWCVT_FFV | VRD(vreg) | VRS2(src));3707}37083709ins = (sljit_ins)1 << (reg_size - elem2_size);3710FAIL_IF(push_inst(compiler, VSETIVLI | RD(TMP_REG1) | ((sljit_ins)elem2_size << 23) | (ins << 15)));37113712switch (elem2_size - elem_size) {3713case 1:3714ins = VZEXT_VF2;3715break;3716case 2:3717ins = VZEXT_VF4;3718break;3719default:3720ins = VZEXT_VF8;3721break;3722}37233724if (type & SLJIT_SIMD_EXTEND_SIGNED)3725ins |= 1 << 15;37263727return push_inst(compiler, ins | VRD(vreg) | VRS2(src));3728}37293730SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_simd_sign(struct sljit_compiler *compiler, sljit_s32 type,3731sljit_s32 vreg,3732sljit_s32 dst, sljit_sw dstw)3733{3734sljit_s32 reg_size = SLJIT_SIMD_GET_REG_SIZE(type);3735sljit_s32 elem_size = SLJIT_SIMD_GET_ELEM_SIZE(type);3736sljit_s32 dst_r = FAST_IS_REG(dst) ? dst : TMP_REG2;37373738CHECK_ERROR();3739CHECK(check_sljit_emit_simd_sign(compiler, type, vreg, dst, dstw));37403741ADJUST_LOCAL_OFFSET(dst, dstw);37423743if (reg_size != 4)3744return SLJIT_ERR_UNSUPPORTED;37453746if (((type & SLJIT_SIMD_FLOAT) && elem_size < 2) || elem_size > 3)3747return SLJIT_ERR_UNSUPPORTED;37483749FAIL_IF(sljit_emit_vsetivli(compiler, type, 0));3750FAIL_IF(push_inst(compiler, VMV_VI | VRD(TMP_VREG1) | (0x0 << 15)));3751FAIL_IF(push_inst(compiler, VMSLE_VI | VRD(TMP_VREG1) | (0x0 << 15) | VRS2(vreg)));37523753FAIL_IF(sljit_emit_vsetivli_size(compiler, 2, 2));3754FAIL_IF(push_inst(compiler, VMV_XS | RD(dst_r) | VRS2(TMP_VREG1)));37553756if (dst & SLJIT_MEM)3757return emit_op_mem(compiler, (type & SLJIT_32) ? INT_DATA : WORD_DATA, dst_r, dst, dstw);3758return SLJIT_SUCCESS;3759}37603761SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_simd_op2(struct sljit_compiler *compiler, sljit_s32 type,3762sljit_s32 dst_vreg, sljit_s32 src1_vreg, sljit_s32 src2, sljit_sw src2w)3763{3764sljit_s32 reg_size = SLJIT_SIMD_GET_REG_SIZE(type);3765sljit_s32 elem_size = SLJIT_SIMD_GET_ELEM_SIZE(type);3766sljit_ins ins = 0;37673768CHECK_ERROR();3769CHECK(check_sljit_emit_simd_op2(compiler, type, dst_vreg, src1_vreg, src2, src2w));37703771ADJUST_LOCAL_OFFSET(src2, src2w);37723773if (reg_size != 4)3774return SLJIT_ERR_UNSUPPORTED;37753776if ((type & SLJIT_SIMD_FLOAT) && (elem_size < 2 || elem_size > 3))3777return SLJIT_ERR_UNSUPPORTED;37783779if (type & SLJIT_SIMD_TEST)3780return SLJIT_SUCCESS;37813782switch (SLJIT_SIMD_GET_OPCODE(type)) {3783case SLJIT_SIMD_OP2_AND:3784ins = VAND_VV;3785break;3786case SLJIT_SIMD_OP2_OR:3787ins = VOR_VV;3788break;3789case SLJIT_SIMD_OP2_XOR:3790ins = VXOR_VV;3791break;3792case SLJIT_SIMD_OP2_SHUFFLE:3793ins = VRGATHER_VV;3794elem_size = 0;3795break;3796}37973798if (elem_size > 3)3799elem_size = 3;38003801FAIL_IF(sljit_emit_vsetivli_size(compiler, reg_size, elem_size));38023803if (src2 & SLJIT_MEM) {3804FAIL_IF(sljit_emit_vmem(compiler, VL | VRD(TMP_VREG1), elem_size, src2, src2w));3805src2 = TMP_VREG1;3806}38073808if (SLJIT_SIMD_GET_OPCODE(type) != SLJIT_SIMD_OP2_SHUFFLE)3809return push_inst(compiler, ins | VRD(dst_vreg) | VRS1(src1_vreg) | VRS2(src2));38103811if (dst_vreg == src2) {3812FAIL_IF(push_inst(compiler, VMV_VV | VRD(TMP_VREG1) | VRS1(src2)));3813src2 = TMP_VREG1;3814}38153816if (dst_vreg == src1_vreg) {3817FAIL_IF(push_inst(compiler, VMV_VV | VRD(TMP_VREG2) | VRS1(src1_vreg)));3818src1_vreg = TMP_VREG2;3819}38203821return push_inst(compiler, ins | VRD(dst_vreg) | VRS1(src2) | VRS2(src1_vreg));3822}38233824SLJIT_API_FUNC_ATTRIBUTE struct sljit_const* sljit_emit_const(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw dstw, sljit_sw init_value)3825{3826struct sljit_const *const_;3827sljit_s32 dst_r;38283829CHECK_ERROR_PTR();3830CHECK_PTR(check_sljit_emit_const(compiler, dst, dstw, init_value));3831ADJUST_LOCAL_OFFSET(dst, dstw);38323833const_ = (struct sljit_const*)ensure_abuf(compiler, sizeof(struct sljit_const));3834PTR_FAIL_IF(!const_);3835set_const(const_, compiler);38363837dst_r = FAST_IS_REG(dst) ? dst : TMP_REG2;3838PTR_FAIL_IF(emit_const(compiler, dst_r, init_value, ADDI | RD(dst_r)));38393840if (dst & SLJIT_MEM)3841PTR_FAIL_IF(emit_op_mem(compiler, WORD_DATA, TMP_REG2, dst, dstw));38423843return const_;3844}38453846SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_mov_addr(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw dstw)3847{3848struct sljit_jump *jump;3849sljit_s32 dst_r;38503851CHECK_ERROR_PTR();3852CHECK_PTR(check_sljit_emit_mov_addr(compiler, dst, dstw));3853ADJUST_LOCAL_OFFSET(dst, dstw);38543855jump = (struct sljit_jump*)ensure_abuf(compiler, sizeof(struct sljit_jump));3856PTR_FAIL_IF(!jump);3857set_mov_addr(jump, compiler, 0);38583859dst_r = FAST_IS_REG(dst) ? dst : TMP_REG2;3860PTR_FAIL_IF(push_inst(compiler, (sljit_ins)dst_r));3861#if (defined SLJIT_CONFIG_RISCV_32 && SLJIT_CONFIG_RISCV_32)3862compiler->size += 1;3863#else /* !SLJIT_CONFIG_RISCV_32 */3864compiler->size += 5;3865#endif /* SLJIT_CONFIG_RISCV_32 */38663867if (dst & SLJIT_MEM)3868PTR_FAIL_IF(emit_op_mem(compiler, WORD_DATA, TMP_REG2, dst, dstw));38693870return jump;3871}38723873SLJIT_API_FUNC_ATTRIBUTE void sljit_set_const(sljit_uw addr, sljit_sw new_constant, sljit_sw executable_offset)3874{3875sljit_set_jump_addr(addr, (sljit_uw)new_constant, executable_offset);3876}387738783879