Path: blob/master/thirdparty/pcre2/deps/sljit/sljit_src/sljitNativeMIPS_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*/2526/* Latest MIPS architecture. */2728#ifdef HAVE_PRCTL29#include <sys/prctl.h>30#endif3132#if !defined(__mips_hard_float) || defined(__mips_single_float)33/* Disable automatic detection, covers both -msoft-float and -mno-float */34#define SLJIT_IS_FPU_AVAILABLE 035#endif3637SLJIT_API_FUNC_ATTRIBUTE const char* sljit_get_platform_name(void)38{39#if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 6)4041#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)42return "MIPS32-R6" SLJIT_CPUINFO;43#else /* !SLJIT_CONFIG_MIPS_32 */44return "MIPS64-R6" SLJIT_CPUINFO;45#endif /* SLJIT_CONFIG_MIPS_32 */4647#elif (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 5)4849#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)50return "MIPS32-R5" SLJIT_CPUINFO;51#else /* !SLJIT_CONFIG_MIPS_32 */52return "MIPS64-R5" SLJIT_CPUINFO;53#endif /* SLJIT_CONFIG_MIPS_32 */5455#elif (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 2)5657#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)58return "MIPS32-R2" SLJIT_CPUINFO;59#else /* !SLJIT_CONFIG_MIPS_32 */60return "MIPS64-R2" SLJIT_CPUINFO;61#endif /* SLJIT_CONFIG_MIPS_32 */6263#elif (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 1)6465#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)66return "MIPS32-R1" SLJIT_CPUINFO;67#else /* !SLJIT_CONFIG_MIPS_32 */68return "MIPS64-R1" SLJIT_CPUINFO;69#endif /* SLJIT_CONFIG_MIPS_32 */7071#else /* SLJIT_MIPS_REV < 1 */72return "MIPS III" SLJIT_CPUINFO;73#endif /* SLJIT_MIPS_REV >= 6 */74}7576/* Length of an instruction word77Both for mips-32 and mips-64 */78typedef sljit_u32 sljit_ins;7980#define TMP_REG1 (SLJIT_NUMBER_OF_REGISTERS + 2)81#define TMP_REG2 (SLJIT_NUMBER_OF_REGISTERS + 3)82#define TMP_REG3 (SLJIT_NUMBER_OF_REGISTERS + 4)8384/* For position independent code, t9 must contain the function address. */85#define PIC_ADDR_REG TMP_REG18687/* Floating point status register. */88#define FCSR_REG 3189/* Return address register. */90#define RETURN_ADDR_REG 319192/* Flags are kept in volatile registers. */93#define EQUAL_FLAG 394#define OTHER_FLAG 19596static const sljit_u8 reg_map[SLJIT_NUMBER_OF_REGISTERS + 7] = {970, 2, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 24, 23, 22, 21, 20, 19, 18, 17, 16, 29, 25, 4, 31, 3, 198};99100#define TMP_FREG1 (SLJIT_NUMBER_OF_FLOAT_REGISTERS + 1)101#define TMP_FREG2 (SLJIT_NUMBER_OF_FLOAT_REGISTERS + 2)102#define TMP_FREG3 (SLJIT_NUMBER_OF_FLOAT_REGISTERS + 3)103104#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)105106static const sljit_u8 freg_map[((SLJIT_NUMBER_OF_FLOAT_REGISTERS + 3) << 1) + 1] = {1070,1080, 14, 2, 4, 6, 8, 18, 30, 28, 26, 24, 22, 20,10912, 10, 16,1101, 15, 3, 5, 7, 9, 19, 31, 29, 27, 25, 23, 21,11113, 11, 17112};113114#else /* !SLJIT_CONFIG_MIPS_32 */115116static const sljit_u8 freg_map[SLJIT_NUMBER_OF_FLOAT_REGISTERS + 4] = {1170, 0, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 1, 2, 3, 4, 5, 6, 7, 8, 9, 31, 30, 29, 28, 27, 26, 25, 24, 12, 11, 10118};119120#endif /* SLJIT_CONFIG_MIPS_32 */121122/* --------------------------------------------------------------------- */123/* Instrucion forms */124/* --------------------------------------------------------------------- */125126#define S(s) ((sljit_ins)reg_map[s] << 21)127#define T(t) ((sljit_ins)reg_map[t] << 16)128#define D(d) ((sljit_ins)reg_map[d] << 11)129#define FT(t) ((sljit_ins)freg_map[t] << 16)130#define FS(s) ((sljit_ins)freg_map[s] << 11)131#define FD(d) ((sljit_ins)freg_map[d] << 6)132/* Absolute registers. */133#define SA(s) ((sljit_ins)(s) << 21)134#define TA(t) ((sljit_ins)(t) << 16)135#define DA(d) ((sljit_ins)(d) << 11)136#define IMM(imm) ((sljit_ins)(imm) & 0xffff)137#define SH_IMM(imm) ((sljit_ins)(imm) << 6)138139#define DR(dr) (reg_map[dr])140#define FR(dr) (freg_map[dr])141#define HI(opcode) ((sljit_ins)(opcode) << 26)142#define LO(opcode) ((sljit_ins)(opcode))143#if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 6)144/* CMP.cond.fmt */145/* S = (20 << 21) D = (21 << 21) */146#define CMP_FMT_S (20 << 21)147#endif /* SLJIT_MIPS_REV >= 6 */148/* S = (16 << 21) D = (17 << 21) */149#define FMT_S (16 << 21)150#define FMT_D (17 << 21)151152#define ABS_S (HI(17) | FMT_S | LO(5))153#define ADD_S (HI(17) | FMT_S | LO(0))154#define ADDIU (HI(9))155#define ADDU (HI(0) | LO(33))156#define AND (HI(0) | LO(36))157#define ANDI (HI(12))158#define B (HI(4))159#define BAL (HI(1) | (17 << 16))160#if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 6)161#define BC1EQZ (HI(17) | (9 << 21) | FT(TMP_FREG3))162#define BC1NEZ (HI(17) | (13 << 21) | FT(TMP_FREG3))163#else /* SLJIT_MIPS_REV < 6 */164#define BC1F (HI(17) | (8 << 21))165#define BC1T (HI(17) | (8 << 21) | (1 << 16))166#endif /* SLJIT_MIPS_REV >= 6 */167#define BEQ (HI(4))168#define BGEZ (HI(1) | (1 << 16))169#define BGTZ (HI(7))170#define BLEZ (HI(6))171#define BLTZ (HI(1) | (0 << 16))172#define BNE (HI(5))173#define BREAK (HI(0) | LO(13))174#define CFC1 (HI(17) | (2 << 21))175#if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 6)176#define C_EQ_S (HI(17) | CMP_FMT_S | LO(2))177#define C_OLE_S (HI(17) | CMP_FMT_S | LO(6))178#define C_OLT_S (HI(17) | CMP_FMT_S | LO(4))179#define C_UEQ_S (HI(17) | CMP_FMT_S | LO(3))180#define C_ULE_S (HI(17) | CMP_FMT_S | LO(7))181#define C_ULT_S (HI(17) | CMP_FMT_S | LO(5))182#define C_UN_S (HI(17) | CMP_FMT_S | LO(1))183#define C_FD (FD(TMP_FREG3))184#else /* SLJIT_MIPS_REV < 6 */185#define C_EQ_S (HI(17) | FMT_S | LO(50))186#define C_OLE_S (HI(17) | FMT_S | LO(54))187#define C_OLT_S (HI(17) | FMT_S | LO(52))188#define C_UEQ_S (HI(17) | FMT_S | LO(51))189#define C_ULE_S (HI(17) | FMT_S | LO(55))190#define C_ULT_S (HI(17) | FMT_S | LO(53))191#define C_UN_S (HI(17) | FMT_S | LO(49))192#define C_FD (0)193#endif /* SLJIT_MIPS_REV >= 6 */194#define CVT_S_S (HI(17) | FMT_S | LO(32))195#define DADDIU (HI(25))196#define DADDU (HI(0) | LO(45))197#if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 6)198#define DDIV (HI(0) | (2 << 6) | LO(30))199#define DDIVU (HI(0) | (2 << 6) | LO(31))200#define DMOD (HI(0) | (3 << 6) | LO(30))201#define DMODU (HI(0) | (3 << 6) | LO(31))202#define DIV (HI(0) | (2 << 6) | LO(26))203#define DIVU (HI(0) | (2 << 6) | LO(27))204#define DMUH (HI(0) | (3 << 6) | LO(28))205#define DMUHU (HI(0) | (3 << 6) | LO(29))206#define DMUL (HI(0) | (2 << 6) | LO(28))207#define DMULU (HI(0) | (2 << 6) | LO(29))208#else /* SLJIT_MIPS_REV < 6 */209#define DDIV (HI(0) | LO(30))210#define DDIVU (HI(0) | LO(31))211#define DIV (HI(0) | LO(26))212#define DIVU (HI(0) | LO(27))213#define DMULT (HI(0) | LO(28))214#define DMULTU (HI(0) | LO(29))215#endif /* SLJIT_MIPS_REV >= 6 */216#define DIV_S (HI(17) | FMT_S | LO(3))217#if defined(SLJIT_MIPS_REV) && SLJIT_MIPS_REV >= 2218#define DINSU (HI(31) | LO(6))219#endif /* SLJIT_MIPS_REV >= 2 */220#define DMFC1 (HI(17) | (1 << 21))221#define DMTC1 (HI(17) | (5 << 21))222#if defined(SLJIT_MIPS_REV) && SLJIT_MIPS_REV >= 2223#define DROTR (HI(0) | (1 << 21) | LO(58))224#define DROTR32 (HI(0) | (1 << 21) | LO(62))225#define DROTRV (HI(0) | (1 << 6) | LO(22))226#define DSBH (HI(31) | (2 << 6) | LO(36))227#define DSHD (HI(31) | (5 << 6) | LO(36))228#endif /* SLJIT_MIPS_REV >= 2 */229#define DSLL (HI(0) | LO(56))230#define DSLL32 (HI(0) | LO(60))231#define DSLLV (HI(0) | LO(20))232#define DSRA (HI(0) | LO(59))233#define DSRA32 (HI(0) | LO(63))234#define DSRAV (HI(0) | LO(23))235#define DSRL (HI(0) | LO(58))236#define DSRL32 (HI(0) | LO(62))237#define DSRLV (HI(0) | LO(22))238#define DSUBU (HI(0) | LO(47))239#define J (HI(2))240#define JAL (HI(3))241#define JALR (HI(0) | LO(9))242#if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 6)243#define JR (HI(0) | LO(9))244#else /* SLJIT_MIPS_REV < 6 */245#define JR (HI(0) | LO(8))246#endif /* SLJIT_MIPS_REV >= 6 */247#define LD (HI(55))248#define LDL (HI(26))249#define LDR (HI(27))250#define LDC1 (HI(53))251#define LL (HI(48))252#define LLD (HI(52))253#define LUI (HI(15))254#define LW (HI(35))255#define LWL (HI(34))256#define LWR (HI(38))257#define LWC1 (HI(49))258#define MFC1 (HI(17))259#if defined(SLJIT_MIPS_REV) && SLJIT_MIPS_REV >= 2260#define MFHC1 (HI(17) | (3 << 21))261#endif /* SLJIT_MIPS_REV >= 2 */262#if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 6)263#define MOD (HI(0) | (3 << 6) | LO(26))264#define MODU (HI(0) | (3 << 6) | LO(27))265#else /* SLJIT_MIPS_REV < 6 */266#define MFHI (HI(0) | LO(16))267#define MFLO (HI(0) | LO(18))268#endif /* SLJIT_MIPS_REV >= 6 */269#define MTC1 (HI(17) | (4 << 21))270#if defined(SLJIT_MIPS_REV) && SLJIT_MIPS_REV >= 2271#define MTHC1 (HI(17) | (7 << 21))272#endif /* SLJIT_MIPS_REV >= 2 */273#if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 6)274#define MUH (HI(0) | (3 << 6) | LO(24))275#define MUHU (HI(0) | (3 << 6) | LO(25))276#define MUL (HI(0) | (2 << 6) | LO(24))277#define MULU (HI(0) | (2 << 6) | LO(25))278#else /* SLJIT_MIPS_REV < 6 */279#define MULT (HI(0) | LO(24))280#define MULTU (HI(0) | LO(25))281#endif /* SLJIT_MIPS_REV >= 6 */282#define MUL_S (HI(17) | FMT_S | LO(2))283#define NEG_S (HI(17) | FMT_S | LO(7))284#define NOP (HI(0) | LO(0))285#define NOR (HI(0) | LO(39))286#define OR (HI(0) | LO(37))287#define ORI (HI(13))288#if defined(SLJIT_MIPS_REV) && SLJIT_MIPS_REV >= 2289#define ROTR (HI(0) | (1 << 21) | LO(2))290#define ROTRV (HI(0) | (1 << 6) | LO(6))291#endif /* SLJIT_MIPS_REV >= 2 */292#define SC (HI(56))293#define SCD (HI(60))294#define SD (HI(63))295#define SDL (HI(44))296#define SDR (HI(45))297#define SDC1 (HI(61))298#define SLT (HI(0) | LO(42))299#define SLTI (HI(10))300#define SLTIU (HI(11))301#define SLTU (HI(0) | LO(43))302#define SLL (HI(0) | LO(0))303#define SLLV (HI(0) | LO(4))304#define SRL (HI(0) | LO(2))305#define SRLV (HI(0) | LO(6))306#define SRA (HI(0) | LO(3))307#define SRAV (HI(0) | LO(7))308#define SUB_S (HI(17) | FMT_S | LO(1))309#define SUBU (HI(0) | LO(35))310#define SW (HI(43))311#define SWL (HI(42))312#define SWR (HI(46))313#define SWC1 (HI(57))314#define SYNC (HI(0) | LO(15))315#define TRUNC_W_S (HI(17) | FMT_S | LO(13))316#if defined(SLJIT_MIPS_REV) && SLJIT_MIPS_REV >= 2317#define WSBH (HI(31) | (2 << 6) | LO(32))318#endif /* SLJIT_MIPS_REV >= 2 */319#define XOR (HI(0) | LO(38))320#define XORI (HI(14))321322#if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 1)323#define CLZ (HI(28) | LO(32))324#if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 6)325#define DCLZ (LO(18))326#else /* SLJIT_MIPS_REV < 6 */327#define DCLZ (HI(28) | LO(36))328#define MOVF (HI(0) | (0 << 16) | LO(1))329#define MOVF_S (HI(17) | FMT_S | (0 << 16) | LO(17))330#define MOVN (HI(0) | LO(11))331#define MOVN_S (HI(17) | FMT_S | LO(19))332#define MOVT (HI(0) | (1 << 16) | LO(1))333#define MOVT_S (HI(17) | FMT_S | (1 << 16) | LO(17))334#define MOVZ (HI(0) | LO(10))335#define MOVZ_S (HI(17) | FMT_S | LO(18))336#define MUL (HI(28) | LO(2))337#endif /* SLJIT_MIPS_REV >= 6 */338#define PREF (HI(51))339#define PREFX (HI(19) | LO(15))340#if defined(SLJIT_MIPS_REV) && SLJIT_MIPS_REV >= 2341#define SEB (HI(31) | (16 << 6) | LO(32))342#define SEH (HI(31) | (24 << 6) | LO(32))343#endif /* SLJIT_MIPS_REV >= 2 */344#endif /* SLJIT_MIPS_REV >= 1 */345346#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)347#define ADDU_W ADDU348#define ADDIU_W ADDIU349#define SLL_W SLL350#define SRA_W SRA351#define SUBU_W SUBU352#define STORE_W SW353#define LOAD_W LW354#else355#define ADDU_W DADDU356#define ADDIU_W DADDIU357#define SLL_W DSLL358#define SRA_W DSRA359#define SUBU_W DSUBU360#define STORE_W SD361#define LOAD_W LD362#endif363364#define MOV_fmt(f) (HI(17) | f | LO(6))365366#define SIMM_MAX (0x7fff)367#define SIMM_MIN (-0x8000)368#define UIMM_MAX (0xffff)369370#define CPU_FEATURE_DETECTED (1 << 0)371#define CPU_FEATURE_FPU (1 << 1)372#define CPU_FEATURE_FP64 (1 << 2)373#define CPU_FEATURE_FR (1 << 3)374375static sljit_u32 cpu_feature_list = 0;376377#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32) \378&& (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)379380static sljit_s32 function_check_is_freg(struct sljit_compiler *compiler, sljit_s32 fr, sljit_s32 is_32)381{382if (compiler->scratches == -1)383return 0;384385if (is_32 && fr >= SLJIT_F64_SECOND(SLJIT_FR0))386fr -= SLJIT_F64_SECOND(0);387388return (fr >= SLJIT_FR0 && fr < (SLJIT_FR0 + compiler->real_fscratches))389|| (fr > (SLJIT_FS0 - compiler->real_fsaveds) && fr <= SLJIT_FS0)390|| (fr >= SLJIT_TMP_FREGISTER_BASE && fr < (SLJIT_TMP_FREGISTER_BASE + SLJIT_NUMBER_OF_TEMPORARY_FLOAT_REGISTERS));391}392393static sljit_s32 function_check_is_vreg(struct sljit_compiler *compiler, sljit_s32 vr, sljit_s32 type)394{395SLJIT_UNUSED_ARG(compiler);396SLJIT_UNUSED_ARG(vr);397SLJIT_UNUSED_ARG(type);398399/* SIMD is not supported. */400return 0;401}402403#endif /* SLJIT_CONFIG_MIPS_32 && SLJIT_ARGUMENT_CHECKS */404405static void get_cpu_features(void)406{407#if !defined(SLJIT_IS_FPU_AVAILABLE) && defined(__GNUC__)408sljit_u32 fir = 0;409#endif /* !SLJIT_IS_FPU_AVAILABLE && __GNUC__ */410sljit_u32 feature_list = CPU_FEATURE_DETECTED;411412#if defined(SLJIT_IS_FPU_AVAILABLE)413#if SLJIT_IS_FPU_AVAILABLE414feature_list |= CPU_FEATURE_FPU;415#if SLJIT_IS_FPU_AVAILABLE == 64416feature_list |= CPU_FEATURE_FP64;417#endif /* SLJIT_IS_FPU_AVAILABLE == 64 */418#endif /* SLJIT_IS_FPU_AVAILABLE */419#elif defined(__GNUC__)420__asm__ ("cfc1 %0, $0" : "=r"(fir));421if ((fir & (0x3 << 16)) == (0x3 << 16))422feature_list |= CPU_FEATURE_FPU;423424#if (defined(SLJIT_CONFIG_MIPS_64) && SLJIT_CONFIG_MIPS_64) \425&& (!defined(SLJIT_MIPS_REV) || SLJIT_MIPS_REV < 2)426if ((feature_list & CPU_FEATURE_FPU))427feature_list |= CPU_FEATURE_FP64;428#else /* SLJIT_CONFIG_MIPS32 || SLJIT_MIPS_REV >= 2 */429if ((fir & (1 << 22)))430feature_list |= CPU_FEATURE_FP64;431#endif /* SLJIT_CONFIG_MIPS_64 && SLJIT_MIPS_REV < 2 */432#endif /* SLJIT_IS_FPU_AVAILABLE */433434if ((feature_list & CPU_FEATURE_FPU) && (feature_list & CPU_FEATURE_FP64)) {435#if defined(SLJIT_CONFIG_MIPS_32) && SLJIT_CONFIG_MIPS_32436#if defined(SLJIT_MIPS_REV) && SLJIT_MIPS_REV >= 6437feature_list |= CPU_FEATURE_FR;438#elif defined(SLJIT_DETECT_FR) && SLJIT_DETECT_FR == 0439#if defined(SLJIT_MIPS_REV) && SLJIT_MIPS_REV >= 5440feature_list |= CPU_FEATURE_FR;441#endif /* SLJIT_MIPS_REV >= 5 */442#else443sljit_s32 flag = -1;444#ifndef FR_GET_FP_MODE445sljit_f64 zero = 0.0;446#else /* PR_GET_FP_MODE */447flag = prctl(PR_GET_FP_MODE);448449if (flag > 0)450feature_list |= CPU_FEATURE_FR;451#endif /* FP_GET_PR_MODE */452#if ((defined(SLJIT_DETECT_FR) && SLJIT_DETECT_FR == 2) \453|| (!defined(PR_GET_FP_MODE) && (!defined(SLJIT_DETECT_FR) || SLJIT_DETECT_FR >= 1))) \454&& (defined(__GNUC__) && (defined(__mips) && __mips >= 2))455if (flag < 0) {456__asm__ (".set oddspreg\n"457"lwc1 $f17, %0\n"458"ldc1 $f16, %1\n"459"swc1 $f17, %0\n"460: "+m" (flag) : "m" (zero) : "$f16", "$f17");461if (flag)462feature_list |= CPU_FEATURE_FR;463}464#endif /* (!PR_GET_FP_MODE || (PR_GET_FP_MODE && SLJIT_DETECT_FR == 2)) && __GNUC__ */465#endif /* SLJIT_MIPS_REV >= 6 */466#else /* !SLJIT_CONFIG_MIPS_32 */467/* StatusFR=1 is the only mode supported by the code in MIPS64 */468feature_list |= CPU_FEATURE_FR;469#endif /* SLJIT_CONFIG_MIPS_32 */470}471472cpu_feature_list = feature_list;473}474475/* dest_reg is the absolute name of the register476Useful for reordering instructions in the delay slot. */477static sljit_s32 push_inst(struct sljit_compiler *compiler, sljit_ins ins, sljit_s32 delay_slot)478{479sljit_ins *ptr = (sljit_ins*)ensure_buf(compiler, sizeof(sljit_ins));480SLJIT_ASSERT(delay_slot == MOVABLE_INS || delay_slot >= UNMOVABLE_INS481|| (sljit_ins)delay_slot == ((ins >> 11) & 0x1f)482|| (sljit_ins)delay_slot == ((ins >> 16) & 0x1f));483FAIL_IF(!ptr);484*ptr = ins;485compiler->size++;486compiler->delay_slot = delay_slot;487return SLJIT_SUCCESS;488}489490static SLJIT_INLINE sljit_ins invert_branch(sljit_uw flags)491{492if (flags & IS_BIT26_COND)493return (1 << 26);494#if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 6)495if (flags & IS_BIT23_COND)496return (1 << 23);497#endif /* SLJIT_MIPS_REV >= 6 */498return (1 << 16);499}500501static SLJIT_INLINE sljit_ins* detect_jump_type(struct sljit_jump *jump, sljit_ins *code, sljit_sw executable_offset)502{503sljit_sw diff;504sljit_uw target_addr;505sljit_ins *inst;506sljit_ins saved_inst;507508inst = (sljit_ins *)jump->addr;509510#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)511if (jump->flags & (SLJIT_REWRITABLE_JUMP | IS_CALL))512goto exit;513#else514if (jump->flags & SLJIT_REWRITABLE_JUMP)515goto exit;516#endif517518if (jump->flags & JUMP_ADDR)519target_addr = jump->u.target;520else {521SLJIT_ASSERT(jump->u.label != NULL);522target_addr = (sljit_uw)(code + jump->u.label->size) + (sljit_uw)executable_offset;523}524525if (jump->flags & IS_COND)526inst--;527528#if (defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64)529if (jump->flags & IS_CALL)530goto preserve_addr;531#endif532533/* B instructions. */534if (jump->flags & IS_MOVABLE) {535diff = ((sljit_sw)target_addr - (sljit_sw)inst - executable_offset) >> 2;536if (diff <= SIMM_MAX && diff >= SIMM_MIN) {537jump->flags |= PATCH_B;538539if (!(jump->flags & IS_COND)) {540inst[0] = inst[-1];541inst[-1] = (jump->flags & IS_JAL) ? BAL : B;542jump->addr -= sizeof(sljit_ins);543return inst;544}545saved_inst = inst[0];546inst[0] = inst[-1];547inst[-1] = saved_inst ^ invert_branch(jump->flags);548jump->addr -= 2 * sizeof(sljit_ins);549return inst;550}551} else {552diff = ((sljit_sw)target_addr - (sljit_sw)(inst + 1) - executable_offset) >> 2;553if (diff <= SIMM_MAX && diff >= SIMM_MIN) {554jump->flags |= PATCH_B;555556if (!(jump->flags & IS_COND)) {557inst[0] = (jump->flags & IS_JAL) ? BAL : B;558/* Keep inst[1] */559return inst + 1;560}561inst[0] ^= invert_branch(jump->flags);562inst[1] = NOP;563jump->addr -= sizeof(sljit_ins);564return inst + 1;565}566}567568if (jump->flags & IS_COND) {569if ((jump->flags & IS_MOVABLE) && (target_addr & ~(sljit_uw)0xfffffff) == ((jump->addr + 2 * sizeof(sljit_ins)) & ~(sljit_uw)0xfffffff)) {570jump->flags |= PATCH_J;571saved_inst = inst[0];572inst[0] = inst[-1];573inst[-1] = (saved_inst & 0xffff0000) | 3;574inst[1] = J;575inst[2] = NOP;576return inst + 2;577}578else if ((target_addr & ~(sljit_uw)0xfffffff) == ((jump->addr + 3 * sizeof(sljit_ins)) & ~(sljit_uw)0xfffffff)) {579jump->flags |= PATCH_J;580inst[0] = (inst[0] & 0xffff0000) | 3;581inst[1] = NOP;582inst[2] = J;583inst[3] = NOP;584jump->addr += sizeof(sljit_ins);585return inst + 3;586}587}588else {589/* J instuctions. */590if ((jump->flags & IS_MOVABLE) && (target_addr & ~(sljit_uw)0xfffffff) == (jump->addr & ~(sljit_uw)0xfffffff)) {591jump->flags |= PATCH_J;592inst[0] = inst[-1];593inst[-1] = (jump->flags & IS_JAL) ? JAL : J;594jump->addr -= sizeof(sljit_ins);595return inst;596}597598if ((target_addr & ~(sljit_uw)0xfffffff) == ((jump->addr + sizeof(sljit_ins)) & ~(sljit_uw)0xfffffff)) {599jump->flags |= PATCH_J;600inst[0] = (jump->flags & IS_JAL) ? JAL : J;601/* Keep inst[1] */602return inst + 1;603}604}605606if (jump->flags & IS_COND)607inst++;608609#if (defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64)610preserve_addr:611if (target_addr <= 0x7fffffff) {612jump->flags |= PATCH_ABS32;613if (jump->flags & IS_COND)614inst[-1] -= 4;615616inst[2] = inst[0];617inst[3] = inst[1];618return inst + 3;619}620if (target_addr <= 0x7fffffffffffl) {621jump->flags |= PATCH_ABS48;622if (jump->flags & IS_COND)623inst[-1] -= 2;624625inst[4] = inst[0];626inst[5] = inst[1];627return inst + 5;628}629#endif630631exit:632#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)633inst[2] = inst[0];634inst[3] = inst[1];635return inst + 3;636#else637inst[6] = inst[0];638inst[7] = inst[1];639return inst + 7;640#endif641}642643#ifdef __GNUC__644static __attribute__ ((noinline)) void sljit_cache_flush(void* code, void* code_ptr)645{646SLJIT_CACHE_FLUSH(code, code_ptr);647}648#endif649650#if (defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64)651652static SLJIT_INLINE sljit_sw mov_addr_get_length(struct sljit_jump *jump, sljit_ins *code, sljit_sw executable_offset)653{654sljit_uw addr;655SLJIT_UNUSED_ARG(executable_offset);656657if (jump->flags & JUMP_ADDR)658addr = jump->u.target;659else660addr = (sljit_uw)SLJIT_ADD_EXEC_OFFSET(code + jump->u.label->size, executable_offset);661662if (addr < 0x80000000l) {663jump->flags |= PATCH_ABS32;664return 1;665}666667if (addr < 0x800000000000l) {668jump->flags |= PATCH_ABS48;669return 3;670}671672return 5;673}674675#endif /* SLJIT_CONFIG_MIPS_64 */676677static SLJIT_INLINE void load_addr_to_reg(struct sljit_jump *jump)678{679sljit_uw flags = jump->flags;680sljit_ins *ins = (sljit_ins*)jump->addr;681sljit_uw addr = (flags & JUMP_ADDR) ? jump->u.target : jump->u.label->u.addr;682sljit_u32 reg = (flags & JUMP_MOV_ADDR) ? *ins : PIC_ADDR_REG;683684#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)685ins[0] = LUI | T(reg) | IMM(addr >> 16);686#else /* !SLJIT_CONFIG_MIPS_32 */687if (flags & PATCH_ABS32) {688SLJIT_ASSERT(addr < 0x80000000l);689ins[0] = LUI | T(reg) | IMM(addr >> 16);690}691else if (flags & PATCH_ABS48) {692SLJIT_ASSERT(addr < 0x800000000000l);693ins[0] = LUI | T(reg) | IMM(addr >> 32);694ins[1] = ORI | S(reg) | T(reg) | IMM((addr >> 16) & 0xffff);695ins[2] = DSLL | T(reg) | D(reg) | SH_IMM(16);696ins += 2;697}698else {699ins[0] = LUI | T(reg) | IMM(addr >> 48);700ins[1] = ORI | S(reg) | T(reg) | IMM((addr >> 32) & 0xffff);701ins[2] = DSLL | T(reg) | D(reg) | SH_IMM(16);702ins[3] = ORI | S(reg) | T(reg) | IMM((addr >> 16) & 0xffff);703ins[4] = DSLL | T(reg) | D(reg) | SH_IMM(16);704ins += 4;705}706#endif /* SLJIT_CONFIG_MIPS_32 */707708ins[1] = ORI | S(reg) | T(reg) | IMM(addr & 0xffff);709}710711SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compiler, sljit_s32 options, void *exec_allocator_data)712{713struct sljit_memory_fragment *buf;714sljit_ins *code;715sljit_ins *code_ptr;716sljit_ins *buf_ptr;717sljit_ins *buf_end;718sljit_uw word_count;719SLJIT_NEXT_DEFINE_TYPES;720sljit_sw executable_offset;721sljit_uw addr;722struct sljit_label *label;723struct sljit_jump *jump;724struct sljit_const *const_;725726CHECK_ERROR_PTR();727CHECK_PTR(check_sljit_generate_code(compiler));728reverse_buf(compiler);729730code = (sljit_ins*)allocate_executable_memory(compiler->size * sizeof(sljit_ins), options, exec_allocator_data, &executable_offset);731PTR_FAIL_WITH_EXEC_IF(code);732buf = compiler->buf;733734code_ptr = code;735word_count = 0;736label = compiler->labels;737jump = compiler->jumps;738const_ = compiler->consts;739SLJIT_NEXT_INIT_TYPES();740SLJIT_GET_NEXT_MIN();741742do {743buf_ptr = (sljit_ins*)buf->memory;744buf_end = buf_ptr + (buf->used_size >> 2);745do {746*code_ptr = *buf_ptr++;747if (next_min_addr == word_count) {748SLJIT_ASSERT(!label || label->size >= word_count);749SLJIT_ASSERT(!jump || jump->addr >= word_count);750SLJIT_ASSERT(!const_ || const_->addr >= word_count);751752/* These structures are ordered by their address. */753if (next_min_addr == next_label_size) {754label->u.addr = (sljit_uw)SLJIT_ADD_EXEC_OFFSET(code_ptr, executable_offset);755label->size = (sljit_uw)(code_ptr - code);756label = label->next;757next_label_size = SLJIT_GET_NEXT_SIZE(label);758}759760if (next_min_addr == next_jump_addr) {761if (!(jump->flags & JUMP_MOV_ADDR)) {762#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)763word_count += 2;764#else /* !SLJIT_CONFIG_MIPS_32 */765word_count += 6;766#endif /* SLJIT_CONFIG_MIPS_32 */767jump->addr = (sljit_uw)(code_ptr - 1);768code_ptr = detect_jump_type(jump, code, executable_offset);769} else {770jump->addr = (sljit_uw)code_ptr;771#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)772code_ptr += 1;773word_count += 1;774#else /* !SLJIT_CONFIG_MIPS_32 */775code_ptr += mov_addr_get_length(jump, code, executable_offset);776word_count += 5;777#endif /* SLJIT_CONFIG_MIPS_32 */778}779780jump = jump->next;781next_jump_addr = SLJIT_GET_NEXT_ADDRESS(jump);782} else if (next_min_addr == next_const_addr) {783const_->addr = (sljit_uw)code_ptr;784const_ = const_->next;785next_const_addr = SLJIT_GET_NEXT_ADDRESS(const_);786}787788SLJIT_GET_NEXT_MIN();789}790code_ptr++;791word_count++;792} while (buf_ptr < buf_end);793794buf = buf->next;795} while (buf);796797if (label && label->size == word_count) {798label->u.addr = (sljit_uw)code_ptr;799label->size = (sljit_uw)(code_ptr - code);800label = label->next;801}802803SLJIT_ASSERT(!label);804SLJIT_ASSERT(!jump);805SLJIT_ASSERT(!const_);806SLJIT_ASSERT(code_ptr - code <= (sljit_sw)compiler->size);807808jump = compiler->jumps;809while (jump) {810do {811addr = (jump->flags & JUMP_ADDR) ? jump->u.target : jump->u.label->u.addr;812buf_ptr = (sljit_ins *)jump->addr;813814if (jump->flags & PATCH_B) {815addr = (sljit_uw)((sljit_sw)(addr - (sljit_uw)SLJIT_ADD_EXEC_OFFSET(buf_ptr, executable_offset) - sizeof(sljit_ins)) >> 2);816SLJIT_ASSERT((sljit_sw)addr <= SIMM_MAX && (sljit_sw)addr >= SIMM_MIN);817buf_ptr[0] = (buf_ptr[0] & 0xffff0000) | ((sljit_ins)addr & 0xffff);818break;819}820if (jump->flags & PATCH_J) {821SLJIT_ASSERT((addr & ~(sljit_uw)0xfffffff)822== (((sljit_uw)SLJIT_ADD_EXEC_OFFSET(buf_ptr, executable_offset) + sizeof(sljit_ins)) & ~(sljit_uw)0xfffffff));823buf_ptr[0] |= (sljit_ins)(addr >> 2) & 0x03ffffff;824break;825}826827load_addr_to_reg(jump);828} while (0);829830jump = jump->next;831}832833compiler->error = SLJIT_ERR_COMPILED;834compiler->executable_offset = executable_offset;835compiler->executable_size = (sljit_uw)(code_ptr - code) * sizeof(sljit_ins);836837code = (sljit_ins *)SLJIT_ADD_EXEC_OFFSET(code, executable_offset);838code_ptr = (sljit_ins *)SLJIT_ADD_EXEC_OFFSET(code_ptr, executable_offset);839840#ifndef __GNUC__841SLJIT_CACHE_FLUSH(code, code_ptr);842#else843/* GCC workaround for invalid code generation with -O2. */844sljit_cache_flush(code, code_ptr);845#endif846SLJIT_UPDATE_WX_FLAGS(code, code_ptr, 1);847return code;848}849850SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_has_cpu_feature(sljit_s32 feature_type)851{852switch (feature_type) {853#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32) \854&& (!defined(SLJIT_IS_FPU_AVAILABLE) || SLJIT_IS_FPU_AVAILABLE)855case SLJIT_HAS_F64_AS_F32_PAIR:856if (!cpu_feature_list)857get_cpu_features();858859return (cpu_feature_list & CPU_FEATURE_FR) != 0;860#endif /* SLJIT_CONFIG_MIPS_32 && SLJIT_IS_FPU_AVAILABLE */861case SLJIT_HAS_FPU:862if (!cpu_feature_list)863get_cpu_features();864865return (cpu_feature_list & CPU_FEATURE_FPU) != 0;866case SLJIT_HAS_ZERO_REGISTER:867case SLJIT_HAS_COPY_F32:868case SLJIT_HAS_COPY_F64:869return 1;870#if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 1)871case SLJIT_HAS_CLZ:872case SLJIT_HAS_CMOV:873case SLJIT_HAS_PREFETCH:874case SLJIT_HAS_ATOMIC:875case SLJIT_HAS_MEMORY_BARRIER:876return 1;877878case SLJIT_HAS_CTZ:879return 2;880#endif /* SLJIT_MIPS_REV >= 1 */881#if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 2)882case SLJIT_HAS_REV:883case SLJIT_HAS_ROT:884return 1;885#endif /* SLJIT_MIPS_REV >= 2 */886default:887return 0;888}889}890891SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_cmp_info(sljit_s32 type)892{893SLJIT_UNUSED_ARG(type);894return 0;895}896897/* --------------------------------------------------------------------- */898/* Entry, exit */899/* --------------------------------------------------------------------- */900901/* Creates an index in data_transfer_insts array. */902#define LOAD_DATA 0x01903#define WORD_DATA 0x00904#define BYTE_DATA 0x02905#define HALF_DATA 0x04906#define INT_DATA 0x06907#define SIGNED_DATA 0x08908/* Separates integer and floating point registers */909#define GPR_REG 0x0f910#define DOUBLE_DATA 0x10911#define SINGLE_DATA 0x12912913#define MEM_MASK 0x1f914915#define ARG_TEST 0x00020916#define ALT_KEEP_CACHE 0x00040917#define CUMULATIVE_OP 0x00080918#define LOGICAL_OP 0x00100919#define IMM_OP 0x00200920#define MOVE_OP 0x00400921#define SRC2_IMM 0x00800922923#define UNUSED_DEST 0x01000924#define REG_DEST 0x02000925#define REG1_SOURCE 0x04000926#define REG2_SOURCE 0x08000927#define SLOW_SRC1 0x10000928#define SLOW_SRC2 0x20000929#define SLOW_DEST 0x40000930931static sljit_s32 emit_op_mem(struct sljit_compiler *compiler, sljit_s32 flags, sljit_s32 reg_ar, sljit_s32 arg, sljit_sw argw);932static sljit_s32 emit_stack_frame_release(struct sljit_compiler *compiler, sljit_s32 frame_size, sljit_ins *ins_ptr);933934#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)935#define SELECT_OP(d, w) (w)936#else937#define SELECT_OP(d, w) (!(op & SLJIT_32) ? (d) : (w))938#endif939940#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)941#include "sljitNativeMIPS_32.c"942#else943#include "sljitNativeMIPS_64.c"944#endif945946SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_enter(struct sljit_compiler *compiler,947sljit_s32 options, sljit_s32 arg_types,948sljit_s32 scratches, sljit_s32 saveds, sljit_s32 local_size)949{950sljit_s32 fscratches = ENTER_GET_FLOAT_REGS(scratches);951sljit_s32 fsaveds = ENTER_GET_FLOAT_REGS(saveds);952sljit_ins base;953sljit_s32 i, tmp, offset;954sljit_s32 arg_count, word_arg_count, float_arg_count;955sljit_s32 saved_arg_count = SLJIT_KEPT_SAVEDS_COUNT(options);956957CHECK_ERROR();958CHECK(check_sljit_emit_enter(compiler, options, arg_types, scratches, saveds, local_size));959set_emit_enter(compiler, options, arg_types, scratches, saveds, local_size);960961scratches = ENTER_GET_REGS(scratches);962saveds = ENTER_GET_REGS(saveds);963964local_size += GET_SAVED_REGISTERS_SIZE(scratches, saveds - saved_arg_count, 1);965#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)966if (fsaveds > 0 || fscratches >= SLJIT_FIRST_SAVED_FLOAT_REG) {967if ((local_size & SSIZE_OF(sw)) != 0)968local_size += SSIZE_OF(sw);969local_size += GET_SAVED_FLOAT_REGISTERS_SIZE(fscratches, fsaveds, f64);970}971972local_size = (local_size + SLJIT_LOCALS_OFFSET + 15) & ~0xf;973#else974local_size += GET_SAVED_FLOAT_REGISTERS_SIZE(fscratches, fsaveds, f64);975local_size = (local_size + SLJIT_LOCALS_OFFSET + 31) & ~0x1f;976#endif977compiler->local_size = local_size;978979offset = 0;980#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)981if (!(options & SLJIT_ENTER_REG_ARG)) {982tmp = arg_types >> SLJIT_ARG_SHIFT;983arg_count = 0;984985while (tmp) {986offset = arg_count;987if ((tmp & SLJIT_ARG_MASK) == SLJIT_ARG_TYPE_F64) {988if ((arg_count & 0x1) != 0)989arg_count++;990arg_count++;991}992993arg_count++;994tmp >>= SLJIT_ARG_SHIFT;995}996997compiler->args_size = (sljit_uw)arg_count << 2;998offset = (offset >= 4) ? (offset << 2) : 0;999}1000#endif /* SLJIT_CONFIG_MIPS_32 */10011002if (local_size + offset <= -SIMM_MIN) {1003/* Frequent case. */1004FAIL_IF(push_inst(compiler, ADDIU_W | S(SLJIT_SP) | T(SLJIT_SP) | IMM(-local_size), DR(SLJIT_SP)));1005base = S(SLJIT_SP);1006offset = local_size - SSIZE_OF(sw);1007} else {1008FAIL_IF(load_immediate(compiler, OTHER_FLAG, local_size));1009FAIL_IF(push_inst(compiler, ADDU_W | S(SLJIT_SP) | TA(0) | D(TMP_REG1), DR(TMP_REG1)));1010FAIL_IF(push_inst(compiler, SUBU_W | S(SLJIT_SP) | TA(OTHER_FLAG) | D(SLJIT_SP), DR(SLJIT_SP)));1011base = S(TMP_REG1);1012offset = -SSIZE_OF(sw);1013#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)1014local_size = 0;1015#endif1016}10171018FAIL_IF(push_inst(compiler, STORE_W | base | TA(RETURN_ADDR_REG) | IMM(offset), UNMOVABLE_INS));10191020tmp = SLJIT_S0 - saveds;1021for (i = SLJIT_S0 - saved_arg_count; i > tmp; i--) {1022offset -= SSIZE_OF(sw);1023FAIL_IF(push_inst(compiler, STORE_W | base | T(i) | IMM(offset), MOVABLE_INS));1024}10251026for (i = scratches; i >= SLJIT_FIRST_SAVED_REG; i--) {1027offset -= SSIZE_OF(sw);1028FAIL_IF(push_inst(compiler, STORE_W | base | T(i) | IMM(offset), MOVABLE_INS));1029}10301031#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)1032/* This alignment is valid because offset is not used after storing FPU regs. */1033if ((offset & SSIZE_OF(sw)) != 0)1034offset -= SSIZE_OF(sw);1035#endif10361037tmp = SLJIT_FS0 - fsaveds;1038for (i = SLJIT_FS0; i > tmp; i--) {1039offset -= SSIZE_OF(f64);1040FAIL_IF(push_inst(compiler, SDC1 | base | FT(i) | IMM(offset), MOVABLE_INS));1041}10421043for (i = fscratches; i >= SLJIT_FIRST_SAVED_FLOAT_REG; i--) {1044offset -= SSIZE_OF(f64);1045FAIL_IF(push_inst(compiler, SDC1 | base | FT(i) | IMM(offset), MOVABLE_INS));1046}10471048if (options & SLJIT_ENTER_REG_ARG)1049return SLJIT_SUCCESS;10501051arg_types >>= SLJIT_ARG_SHIFT;1052arg_count = 0;1053word_arg_count = 0;1054float_arg_count = 0;10551056#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)1057/* The first maximum two floating point arguments are passed in floating point1058registers if no integer argument precedes them. The first 16 byte data is1059passed in four integer registers, the rest is placed onto the stack.1060The floating point registers are also part of the first 16 byte data, so1061their corresponding integer registers are not used when they are present. */10621063while (arg_types) {1064switch (arg_types & SLJIT_ARG_MASK) {1065case SLJIT_ARG_TYPE_F64:1066float_arg_count++;1067if ((arg_count & 0x1) != 0)1068arg_count++;10691070if (word_arg_count == 0 && float_arg_count <= 2) {1071if (float_arg_count == 1)1072FAIL_IF(push_inst(compiler, MOV_fmt(FMT_D) | FS(TMP_FREG1) | FD(SLJIT_FR0), MOVABLE_INS));1073} else if (arg_count < 4) {1074FAIL_IF(push_inst(compiler, MTC1 | TA(4 + arg_count) | FS(float_arg_count), MOVABLE_INS));1075switch (cpu_feature_list & CPU_FEATURE_FR) {1076#if defined(SLJIT_MIPS_REV) && SLJIT_MIPS_REV >= 21077case CPU_FEATURE_FR:1078FAIL_IF(push_inst(compiler, MTHC1 | TA(5 + arg_count) | FS(float_arg_count), MOVABLE_INS));1079break;1080#endif /* SLJIT_MIPS_REV >= 2 */1081default:1082FAIL_IF(push_inst(compiler, MTC1 | TA(5 + arg_count) | FS(float_arg_count) | (1 << 11), MOVABLE_INS));1083break;1084}1085} else1086FAIL_IF(push_inst(compiler, LDC1 | base | FT(float_arg_count) | IMM(local_size + (arg_count << 2)), MOVABLE_INS));1087arg_count++;1088break;1089case SLJIT_ARG_TYPE_F32:1090float_arg_count++;10911092if (word_arg_count == 0 && float_arg_count <= 2) {1093if (float_arg_count == 1)1094FAIL_IF(push_inst(compiler, MOV_fmt(FMT_S) | FS(TMP_FREG1) | FD(SLJIT_FR0), MOVABLE_INS));1095} else if (arg_count < 4)1096FAIL_IF(push_inst(compiler, MTC1 | TA(4 + arg_count) | FS(float_arg_count), MOVABLE_INS));1097else1098FAIL_IF(push_inst(compiler, LWC1 | base | FT(float_arg_count) | IMM(local_size + (arg_count << 2)), MOVABLE_INS));1099break;1100default:1101word_arg_count++;11021103if (!(arg_types & SLJIT_ARG_TYPE_SCRATCH_REG)) {1104tmp = SLJIT_S0 - saved_arg_count;1105saved_arg_count++;1106} else if (word_arg_count != arg_count + 1 || arg_count == 0)1107tmp = word_arg_count;1108else1109break;11101111if (arg_count < 4)1112FAIL_IF(push_inst(compiler, ADDU_W | SA(4 + arg_count) | TA(0) | D(tmp), DR(tmp)));1113else1114FAIL_IF(push_inst(compiler, LW | base | T(tmp) | IMM(local_size + (arg_count << 2)), DR(tmp)));1115break;1116}1117arg_count++;1118arg_types >>= SLJIT_ARG_SHIFT;1119}11201121SLJIT_ASSERT(compiler->args_size == (sljit_uw)arg_count << 2);1122#else /* !SLJIT_CONFIG_MIPS_32 */1123while (arg_types) {1124arg_count++;1125switch (arg_types & SLJIT_ARG_MASK) {1126case SLJIT_ARG_TYPE_F64:1127float_arg_count++;1128if (arg_count != float_arg_count)1129FAIL_IF(push_inst(compiler, MOV_fmt(FMT_D) | FS(arg_count) | FD(float_arg_count), MOVABLE_INS));1130else if (arg_count == 1)1131FAIL_IF(push_inst(compiler, MOV_fmt(FMT_D) | FS(TMP_FREG1) | FD(SLJIT_FR0), MOVABLE_INS));1132break;1133case SLJIT_ARG_TYPE_F32:1134float_arg_count++;1135if (arg_count != float_arg_count)1136FAIL_IF(push_inst(compiler, MOV_fmt(FMT_S) | FS(arg_count) | FD(float_arg_count), MOVABLE_INS));1137else if (arg_count == 1)1138FAIL_IF(push_inst(compiler, MOV_fmt(FMT_S) | FS(TMP_FREG1) | FD(SLJIT_FR0), MOVABLE_INS));1139break;1140default:1141word_arg_count++;11421143if (!(arg_types & SLJIT_ARG_TYPE_SCRATCH_REG)) {1144tmp = SLJIT_S0 - saved_arg_count;1145saved_arg_count++;1146} else if (word_arg_count != arg_count || word_arg_count <= 1)1147tmp = word_arg_count;1148else1149break;11501151FAIL_IF(push_inst(compiler, ADDU_W | SA(3 + arg_count) | TA(0) | D(tmp), DR(tmp)));1152break;1153}1154arg_types >>= SLJIT_ARG_SHIFT;1155}1156#endif /* SLJIT_CONFIG_MIPS_32 */11571158return SLJIT_SUCCESS;1159}11601161SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_set_context(struct sljit_compiler *compiler,1162sljit_s32 options, sljit_s32 arg_types,1163sljit_s32 scratches, sljit_s32 saveds, sljit_s32 local_size)1164{1165sljit_s32 fscratches = ENTER_GET_FLOAT_REGS(scratches);1166sljit_s32 fsaveds = ENTER_GET_FLOAT_REGS(saveds);11671168CHECK_ERROR();1169CHECK(check_sljit_set_context(compiler, options, arg_types, scratches, saveds, local_size));1170set_emit_enter(compiler, options, arg_types, scratches, saveds, local_size);11711172scratches = ENTER_GET_REGS(scratches);1173saveds = ENTER_GET_REGS(saveds);11741175local_size += GET_SAVED_REGISTERS_SIZE(scratches, saveds - SLJIT_KEPT_SAVEDS_COUNT(options), 1);1176#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)1177if (fsaveds > 0 || fscratches >= SLJIT_FIRST_SAVED_FLOAT_REG) {1178if ((local_size & SSIZE_OF(sw)) != 0)1179local_size += SSIZE_OF(sw);1180local_size += GET_SAVED_FLOAT_REGISTERS_SIZE(fscratches, fsaveds, f64);1181}11821183compiler->local_size = (local_size + SLJIT_LOCALS_OFFSET + 15) & ~0xf;1184#else1185local_size += GET_SAVED_FLOAT_REGISTERS_SIZE(fscratches, fsaveds, f64);1186compiler->local_size = (local_size + SLJIT_LOCALS_OFFSET + 31) & ~0x1f;1187#endif1188return SLJIT_SUCCESS;1189}11901191static sljit_s32 emit_stack_frame_release(struct sljit_compiler *compiler, sljit_s32 frame_size, sljit_ins *ins_ptr)1192{1193sljit_s32 local_size, i, tmp, offset;1194sljit_s32 load_return_addr = (frame_size == 0);1195sljit_s32 scratches = compiler->scratches;1196sljit_s32 saveds = compiler->saveds;1197sljit_s32 fsaveds = compiler->fsaveds;1198sljit_s32 fscratches = compiler->fscratches;1199sljit_s32 kept_saveds_count = SLJIT_KEPT_SAVEDS_COUNT(compiler->options);12001201SLJIT_ASSERT(frame_size == 1 || (frame_size & 0xf) == 0);1202frame_size &= ~0xf;12031204local_size = compiler->local_size;12051206tmp = GET_SAVED_REGISTERS_SIZE(scratches, saveds - kept_saveds_count, 1);1207#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)1208if (fsaveds > 0 || fscratches >= SLJIT_FIRST_SAVED_FLOAT_REG) {1209if ((tmp & SSIZE_OF(sw)) != 0)1210tmp += SSIZE_OF(sw);1211tmp += GET_SAVED_FLOAT_REGISTERS_SIZE(fscratches, fsaveds, f64);1212}1213#else1214tmp += GET_SAVED_FLOAT_REGISTERS_SIZE(fscratches, fsaveds, f64);1215#endif12161217if (local_size <= SIMM_MAX) {1218if (local_size < frame_size) {1219FAIL_IF(push_inst(compiler, ADDIU_W | S(SLJIT_SP) | T(SLJIT_SP) | IMM(local_size - frame_size), DR(SLJIT_SP)));1220local_size = frame_size;1221}1222} else {1223if (tmp < frame_size)1224tmp = frame_size;12251226FAIL_IF(load_immediate(compiler, DR(TMP_REG2), local_size - tmp));1227FAIL_IF(push_inst(compiler, ADDU_W | S(SLJIT_SP) | T(TMP_REG2) | D(SLJIT_SP), DR(SLJIT_SP)));1228local_size = tmp;1229}12301231SLJIT_ASSERT(local_size >= frame_size);12321233offset = local_size - SSIZE_OF(sw);1234if (load_return_addr)1235FAIL_IF(push_inst(compiler, LOAD_W | S(SLJIT_SP) | TA(RETURN_ADDR_REG) | IMM(offset), RETURN_ADDR_REG));12361237tmp = SLJIT_S0 - saveds;1238for (i = SLJIT_S0 - kept_saveds_count; i > tmp; i--) {1239offset -= SSIZE_OF(sw);1240FAIL_IF(push_inst(compiler, LOAD_W | S(SLJIT_SP) | T(i) | IMM(offset), MOVABLE_INS));1241}12421243for (i = scratches; i >= SLJIT_FIRST_SAVED_REG; i--) {1244offset -= SSIZE_OF(sw);1245FAIL_IF(push_inst(compiler, LOAD_W | S(SLJIT_SP) | T(i) | IMM(offset), MOVABLE_INS));1246}12471248#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)1249/* This alignment is valid because offset is not used after storing FPU regs. */1250if ((offset & SSIZE_OF(sw)) != 0)1251offset -= SSIZE_OF(sw);1252#endif12531254tmp = SLJIT_FS0 - fsaveds;1255for (i = SLJIT_FS0; i > tmp; i--) {1256offset -= SSIZE_OF(f64);1257FAIL_IF(push_inst(compiler, LDC1 | S(SLJIT_SP) | FT(i) | IMM(offset), MOVABLE_INS));1258}12591260for (i = fscratches; i >= SLJIT_FIRST_SAVED_FLOAT_REG; i--) {1261offset -= SSIZE_OF(f64);1262FAIL_IF(push_inst(compiler, LDC1 | S(SLJIT_SP) | FT(i) | IMM(offset), MOVABLE_INS));1263}12641265if (local_size > frame_size)1266*ins_ptr = ADDIU_W | S(SLJIT_SP) | T(SLJIT_SP) | IMM(local_size - frame_size);1267else1268*ins_ptr = NOP;12691270return SLJIT_SUCCESS;1271}12721273SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_return_void(struct sljit_compiler *compiler)1274{1275sljit_ins ins;12761277CHECK_ERROR();1278CHECK(check_sljit_emit_return_void(compiler));12791280emit_stack_frame_release(compiler, 0, &ins);12811282FAIL_IF(push_inst(compiler, JR | SA(RETURN_ADDR_REG), UNMOVABLE_INS));1283return push_inst(compiler, ins, UNMOVABLE_INS);1284}12851286SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_return_to(struct sljit_compiler *compiler,1287sljit_s32 src, sljit_sw srcw)1288{1289sljit_ins ins;12901291CHECK_ERROR();1292CHECK(check_sljit_emit_return_to(compiler, src, srcw));12931294if (src & SLJIT_MEM) {1295ADJUST_LOCAL_OFFSET(src, srcw);1296FAIL_IF(emit_op_mem(compiler, WORD_DATA | LOAD_DATA, DR(PIC_ADDR_REG), src, srcw));1297src = PIC_ADDR_REG;1298srcw = 0;1299} else if (src >= SLJIT_FIRST_SAVED_REG && src <= (SLJIT_S0 - SLJIT_KEPT_SAVEDS_COUNT(compiler->options))) {1300FAIL_IF(push_inst(compiler, ADDU_W | S(src) | TA(0) | D(PIC_ADDR_REG), DR(PIC_ADDR_REG)));1301src = PIC_ADDR_REG;1302srcw = 0;1303}13041305FAIL_IF(emit_stack_frame_release(compiler, 1, &ins));13061307if (src != SLJIT_IMM) {1308FAIL_IF(push_inst(compiler, JR | S(src), UNMOVABLE_INS));1309return push_inst(compiler, ins, UNMOVABLE_INS);1310}13111312if (ins != NOP)1313FAIL_IF(push_inst(compiler, ins, MOVABLE_INS));13141315SLJIT_SKIP_CHECKS(compiler);1316return sljit_emit_ijump(compiler, SLJIT_JUMP, src, srcw);1317}13181319/* --------------------------------------------------------------------- */1320/* Operators */1321/* --------------------------------------------------------------------- */13221323#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)1324#define ARCH_32_64(a, b) a1325#else1326#define ARCH_32_64(a, b) b1327#endif13281329static const sljit_ins data_transfer_insts[16 + 4] = {1330/* u w s */ ARCH_32_64(HI(43) /* sw */, HI(63) /* sd */),1331/* u w l */ ARCH_32_64(HI(35) /* lw */, HI(55) /* ld */),1332/* u b s */ HI(40) /* sb */,1333/* u b l */ HI(36) /* lbu */,1334/* u h s */ HI(41) /* sh */,1335/* u h l */ HI(37) /* lhu */,1336/* u i s */ HI(43) /* sw */,1337/* u i l */ ARCH_32_64(HI(35) /* lw */, HI(39) /* lwu */),13381339/* s w s */ ARCH_32_64(HI(43) /* sw */, HI(63) /* sd */),1340/* s w l */ ARCH_32_64(HI(35) /* lw */, HI(55) /* ld */),1341/* s b s */ HI(40) /* sb */,1342/* s b l */ HI(32) /* lb */,1343/* s h s */ HI(41) /* sh */,1344/* s h l */ HI(33) /* lh */,1345/* s i s */ HI(43) /* sw */,1346/* s i l */ HI(35) /* lw */,13471348/* d s */ HI(61) /* sdc1 */,1349/* d l */ HI(53) /* ldc1 */,1350/* s s */ HI(57) /* swc1 */,1351/* s l */ HI(49) /* lwc1 */,1352};13531354#undef ARCH_32_6413551356/* reg_ar is an absoulute register! */13571358/* Can perform an operation using at most 1 instruction. */1359static sljit_s32 getput_arg_fast(struct sljit_compiler *compiler, sljit_s32 flags, sljit_s32 reg_ar, sljit_s32 arg, sljit_sw argw)1360{1361SLJIT_ASSERT(arg & SLJIT_MEM);13621363if (!(arg & OFFS_REG_MASK) && argw <= SIMM_MAX && argw >= SIMM_MIN) {1364/* Works for both absoulte and relative addresses. */1365if (SLJIT_UNLIKELY(flags & ARG_TEST))1366return 1;1367FAIL_IF(push_inst(compiler, data_transfer_insts[flags & MEM_MASK] | S(arg & REG_MASK)1368| TA(reg_ar) | IMM(argw), ((flags & MEM_MASK) <= GPR_REG && (flags & LOAD_DATA)) ? reg_ar : MOVABLE_INS));1369return -1;1370}1371return 0;1372}13731374#define TO_ARGW_HI(argw) (((argw) & ~0xffff) + (((argw) & 0x8000) ? 0x10000 : 0))13751376/* See getput_arg below.1377Note: can_cache is called only for binary operators. */1378static sljit_s32 can_cache(sljit_s32 arg, sljit_sw argw, sljit_s32 next_arg, sljit_sw next_argw)1379{1380SLJIT_ASSERT((arg & SLJIT_MEM) && (next_arg & SLJIT_MEM));13811382/* Simple operation except for updates. */1383if (arg & OFFS_REG_MASK) {1384argw &= 0x3;1385next_argw &= 0x3;1386if (argw && argw == next_argw && (arg == next_arg || (arg & OFFS_REG_MASK) == (next_arg & OFFS_REG_MASK)))1387return 1;1388return 0;1389}13901391if (arg == next_arg) {1392if (((next_argw - argw) <= SIMM_MAX && (next_argw - argw) >= SIMM_MIN)1393|| TO_ARGW_HI(argw) == TO_ARGW_HI(next_argw))1394return 1;1395return 0;1396}13971398return 0;1399}14001401/* Emit the necessary instructions. See can_cache above. */1402static sljit_s32 getput_arg(struct sljit_compiler *compiler, sljit_s32 flags, sljit_s32 reg_ar, sljit_s32 arg, sljit_sw argw, sljit_s32 next_arg, sljit_sw next_argw)1403{1404sljit_s32 tmp_ar, base, delay_slot;1405sljit_sw offset, argw_hi;14061407SLJIT_ASSERT(arg & SLJIT_MEM);1408if (!(next_arg & SLJIT_MEM)) {1409next_arg = 0;1410next_argw = 0;1411}14121413/* Since tmp can be the same as base or offset registers,1414* these might be unavailable after modifying tmp. */1415if ((flags & MEM_MASK) <= GPR_REG && (flags & LOAD_DATA)) {1416tmp_ar = reg_ar;1417delay_slot = reg_ar;1418}1419else {1420tmp_ar = DR(TMP_REG1);1421delay_slot = MOVABLE_INS;1422}1423base = arg & REG_MASK;14241425if (SLJIT_UNLIKELY(arg & OFFS_REG_MASK)) {1426argw &= 0x3;14271428/* Using the cache. */1429if (argw == compiler->cache_argw) {1430if (arg == compiler->cache_arg)1431return push_inst(compiler, data_transfer_insts[flags & MEM_MASK] | S(TMP_REG3) | TA(reg_ar), delay_slot);14321433if ((SLJIT_MEM | (arg & OFFS_REG_MASK)) == compiler->cache_arg) {1434if (arg == next_arg && argw == (next_argw & 0x3)) {1435compiler->cache_arg = arg;1436compiler->cache_argw = argw;1437FAIL_IF(push_inst(compiler, ADDU_W | S(base) | T(TMP_REG3) | D(TMP_REG3), DR(TMP_REG3)));1438return push_inst(compiler, data_transfer_insts[flags & MEM_MASK] | S(TMP_REG3) | TA(reg_ar), delay_slot);1439}1440FAIL_IF(push_inst(compiler, ADDU_W | S(base) | T(TMP_REG3) | DA(tmp_ar), tmp_ar));1441return push_inst(compiler, data_transfer_insts[flags & MEM_MASK] | SA(tmp_ar) | TA(reg_ar), delay_slot);1442}1443}14441445if (SLJIT_UNLIKELY(argw)) {1446compiler->cache_arg = SLJIT_MEM | (arg & OFFS_REG_MASK);1447compiler->cache_argw = argw;1448FAIL_IF(push_inst(compiler, SLL_W | T(OFFS_REG(arg)) | D(TMP_REG3) | SH_IMM(argw), DR(TMP_REG3)));1449}14501451if (arg == next_arg && argw == (next_argw & 0x3)) {1452compiler->cache_arg = arg;1453compiler->cache_argw = argw;1454FAIL_IF(push_inst(compiler, ADDU_W | S(base) | T(!argw ? OFFS_REG(arg) : TMP_REG3) | D(TMP_REG3), DR(TMP_REG3)));1455tmp_ar = DR(TMP_REG3);1456}1457else1458FAIL_IF(push_inst(compiler, ADDU_W | S(base) | T(!argw ? OFFS_REG(arg) : TMP_REG3) | DA(tmp_ar), tmp_ar));1459return push_inst(compiler, data_transfer_insts[flags & MEM_MASK] | SA(tmp_ar) | TA(reg_ar), delay_slot);1460}14611462if (compiler->cache_arg == arg && argw - compiler->cache_argw <= SIMM_MAX && argw - compiler->cache_argw >= SIMM_MIN)1463return push_inst(compiler, data_transfer_insts[flags & MEM_MASK] | S(TMP_REG3) | TA(reg_ar) | IMM(argw - compiler->cache_argw), delay_slot);14641465if (compiler->cache_arg == SLJIT_MEM && (argw - compiler->cache_argw) <= SIMM_MAX && (argw - compiler->cache_argw) >= SIMM_MIN) {1466offset = argw - compiler->cache_argw;1467} else {1468compiler->cache_arg = SLJIT_MEM;14691470argw_hi = TO_ARGW_HI(argw);14711472if (next_arg && next_argw - argw <= SIMM_MAX && next_argw - argw >= SIMM_MIN && argw_hi != TO_ARGW_HI(next_argw)) {1473FAIL_IF(load_immediate(compiler, DR(TMP_REG3), argw));1474compiler->cache_argw = argw;1475offset = 0;1476} else {1477FAIL_IF(load_immediate(compiler, DR(TMP_REG3), argw_hi));1478compiler->cache_argw = argw_hi;1479offset = argw & 0xffff;1480argw = argw_hi;1481}1482}14831484if (!base)1485return push_inst(compiler, data_transfer_insts[flags & MEM_MASK] | S(TMP_REG3) | TA(reg_ar) | IMM(offset), delay_slot);14861487if (arg == next_arg && next_argw - argw <= SIMM_MAX && next_argw - argw >= SIMM_MIN) {1488compiler->cache_arg = arg;1489FAIL_IF(push_inst(compiler, ADDU_W | S(TMP_REG3) | T(base) | D(TMP_REG3), DR(TMP_REG3)));1490return push_inst(compiler, data_transfer_insts[flags & MEM_MASK] | S(TMP_REG3) | TA(reg_ar) | IMM(offset), delay_slot);1491}14921493FAIL_IF(push_inst(compiler, ADDU_W | S(TMP_REG3) | T(base) | DA(tmp_ar), tmp_ar));1494return push_inst(compiler, data_transfer_insts[flags & MEM_MASK] | SA(tmp_ar) | TA(reg_ar) | IMM(offset), delay_slot);1495}14961497static sljit_s32 emit_op_mem(struct sljit_compiler *compiler, sljit_s32 flags, sljit_s32 reg_ar, sljit_s32 arg, sljit_sw argw)1498{1499sljit_s32 tmp_ar, base, delay_slot;15001501if (getput_arg_fast(compiler, flags, reg_ar, arg, argw))1502return compiler->error;15031504if ((flags & MEM_MASK) <= GPR_REG && (flags & LOAD_DATA)) {1505tmp_ar = reg_ar;1506delay_slot = reg_ar;1507}1508else {1509tmp_ar = DR(TMP_REG1);1510delay_slot = MOVABLE_INS;1511}1512base = arg & REG_MASK;15131514if (SLJIT_UNLIKELY(arg & OFFS_REG_MASK)) {1515argw &= 0x3;15161517if (SLJIT_UNLIKELY(argw)) {1518FAIL_IF(push_inst(compiler, SLL_W | T(OFFS_REG(arg)) | DA(tmp_ar) | SH_IMM(argw), tmp_ar));1519FAIL_IF(push_inst(compiler, ADDU_W | SA(tmp_ar) | T(base) | DA(tmp_ar), tmp_ar));1520}1521else1522FAIL_IF(push_inst(compiler, ADDU_W | S(base) | T(OFFS_REG(arg)) | DA(tmp_ar), tmp_ar));1523return push_inst(compiler, data_transfer_insts[flags & MEM_MASK] | SA(tmp_ar) | TA(reg_ar), delay_slot);1524}15251526FAIL_IF(load_immediate(compiler, tmp_ar, TO_ARGW_HI(argw)));15271528if (base != 0)1529FAIL_IF(push_inst(compiler, ADDU_W | SA(tmp_ar) | T(base) | DA(tmp_ar), tmp_ar));15301531return push_inst(compiler, data_transfer_insts[flags & MEM_MASK] | SA(tmp_ar) | TA(reg_ar) | IMM(argw), delay_slot);1532}15331534static 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)1535{1536if (getput_arg_fast(compiler, flags, reg, arg1, arg1w))1537return compiler->error;1538return getput_arg(compiler, flags, reg, arg1, arg1w, arg2, arg2w);1539}15401541#define EMIT_LOGICAL(op_imm, op_reg) \1542if (flags & SRC2_IMM) { \1543if (op & SLJIT_SET_Z) \1544FAIL_IF(push_inst(compiler, op_imm | S(src1) | TA(EQUAL_FLAG) | IMM(src2), EQUAL_FLAG)); \1545if (!(flags & UNUSED_DEST)) \1546FAIL_IF(push_inst(compiler, op_imm | S(src1) | T(dst) | IMM(src2), DR(dst))); \1547} \1548else { \1549if (op & SLJIT_SET_Z) \1550FAIL_IF(push_inst(compiler, op_reg | S(src1) | T(src2) | DA(EQUAL_FLAG), EQUAL_FLAG)); \1551if (!(flags & UNUSED_DEST)) \1552FAIL_IF(push_inst(compiler, op_reg | S(src1) | T(src2) | D(dst), DR(dst))); \1553}15541555#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)15561557#define EMIT_SHIFT(dimm, dimm32, imm, dv, v) \1558op_imm = (imm); \1559op_v = (v);15601561#else /* !SLJIT_CONFIG_MIPS_32 */156215631564#define EMIT_SHIFT(dimm, dimm32, imm, dv, v) \1565op_dimm = (dimm); \1566op_dimm32 = (dimm32); \1567op_imm = (imm); \1568op_dv = (dv); \1569op_v = (v);15701571#endif /* SLJIT_CONFIG_MIPS_32 */15721573#if (!defined SLJIT_MIPS_REV || SLJIT_MIPS_REV < 1)15741575static sljit_s32 emit_clz_ctz(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 dst, sljit_sw src)1576{1577sljit_s32 is_clz = (GET_OPCODE(op) == SLJIT_CLZ);1578#if (defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64)1579sljit_ins word_size = (op & SLJIT_32) ? 32 : 64;1580#else /* !SLJIT_CONFIG_MIPS_64 */1581sljit_ins word_size = 32;1582#endif /* SLJIT_CONFIG_MIPS_64 */15831584/* The TMP_REG2 is the next value. */1585if (src != TMP_REG2)1586FAIL_IF(push_inst(compiler, SELECT_OP(DADDU, ADDU) | S(src) | TA(0) | D(TMP_REG2), DR(TMP_REG2)));15871588FAIL_IF(push_inst(compiler, BEQ | S(TMP_REG2) | TA(0) | IMM(is_clz ? 13 : 14), UNMOVABLE_INS));1589/* The OTHER_FLAG is the counter. Delay slot. */1590FAIL_IF(push_inst(compiler, SELECT_OP(DADDIU, ADDIU) | SA(0) | TA(OTHER_FLAG) | IMM(word_size), OTHER_FLAG));15911592if (!is_clz) {1593FAIL_IF(push_inst(compiler, ANDI | S(TMP_REG2) | T(TMP_REG1) | IMM(1), DR(TMP_REG1)));1594FAIL_IF(push_inst(compiler, BNE | S(TMP_REG1) | TA(0) | IMM(11), UNMOVABLE_INS));1595} else1596FAIL_IF(push_inst(compiler, BLTZ | S(TMP_REG2) | TA(0) | IMM(11), UNMOVABLE_INS));15971598/* Delay slot. */1599FAIL_IF(push_inst(compiler, SELECT_OP(DADDIU, ADDIU) | SA(0) | TA(OTHER_FLAG) | IMM(0), OTHER_FLAG));16001601/* The TMP_REG1 is the next shift. */1602FAIL_IF(push_inst(compiler, SELECT_OP(DADDIU, ADDIU) | SA(0) | T(TMP_REG1) | IMM(word_size), DR(TMP_REG1)));16031604FAIL_IF(push_inst(compiler, SELECT_OP(DADDU, ADDU) | S(TMP_REG2) | TA(0) | DA(EQUAL_FLAG), EQUAL_FLAG));1605FAIL_IF(push_inst(compiler, SELECT_OP(DSRL, SRL) | T(TMP_REG1) | D(TMP_REG1) | SH_IMM(1), DR(TMP_REG1)));16061607FAIL_IF(push_inst(compiler, (is_clz ? SELECT_OP(DSRLV, SRLV) : SELECT_OP(DSLLV, SLLV)) | S(TMP_REG1) | TA(EQUAL_FLAG) | D(TMP_REG2), DR(TMP_REG2)));1608FAIL_IF(push_inst(compiler, BNE | S(TMP_REG2) | TA(0) | IMM(-4), UNMOVABLE_INS));1609/* Delay slot. */1610FAIL_IF(push_inst(compiler, NOP, UNMOVABLE_INS));16111612FAIL_IF(push_inst(compiler, SELECT_OP(DADDIU, ADDIU) | S(TMP_REG1) | T(TMP_REG2) | IMM(-1), DR(TMP_REG2)));1613FAIL_IF(push_inst(compiler, (is_clz ? SELECT_OP(DSRLV, SRLV) : SELECT_OP(DSLLV, SLLV)) | S(TMP_REG2) | TA(EQUAL_FLAG) | D(TMP_REG2), DR(TMP_REG2)));16141615FAIL_IF(push_inst(compiler, BEQ | S(TMP_REG2) | TA(0) | IMM(-7), UNMOVABLE_INS));1616/* Delay slot. */1617FAIL_IF(push_inst(compiler, OR | SA(OTHER_FLAG) | T(TMP_REG1) | DA(OTHER_FLAG), OTHER_FLAG));16181619return push_inst(compiler, SELECT_OP(DADDU, ADDU) | SA(OTHER_FLAG) | TA(0) | D(dst), DR(dst));1620}16211622#endif /* SLJIT_MIPS_REV < 1 */16231624static sljit_s32 emit_rev(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 dst, sljit_sw src)1625{1626#if defined(SLJIT_CONFIG_MIPS_64) && SLJIT_CONFIG_MIPS_641627int is_32 = (op & SLJIT_32);1628#endif /* SLJIT_CONFIG_MIPS_64 */16291630op = GET_OPCODE(op);1631#if defined(SLJIT_MIPS_REV) && SLJIT_MIPS_REV >= 21632#if defined(SLJIT_CONFIG_MIPS_64) && SLJIT_CONFIG_MIPS_641633if (!is_32 && (op == SLJIT_REV)) {1634FAIL_IF(push_inst(compiler, DSBH | T(src) | D(dst), DR(dst)));1635return push_inst(compiler, DSHD | T(dst) | D(dst), DR(dst));1636}1637if (op != SLJIT_REV && src != TMP_REG2) {1638FAIL_IF(push_inst(compiler, SLL | T(src) | D(TMP_REG1), DR(TMP_REG1)));1639src = TMP_REG1;1640}1641#endif /* SLJIT_CONFIG_MIPS_64 */1642FAIL_IF(push_inst(compiler, WSBH | T(src) | D(dst), DR(dst)));1643FAIL_IF(push_inst(compiler, ROTR | T(dst) | D(dst) | SH_IMM(16), DR(dst)));1644#if defined(SLJIT_CONFIG_MIPS_64) && SLJIT_CONFIG_MIPS_641645if (op == SLJIT_REV_U32 && dst != TMP_REG2 && dst != TMP_REG3)1646FAIL_IF(push_inst(compiler, DINSU | T(dst) | SA(0) | (31 << 11), DR(dst)));1647#endif /* SLJIT_CONFIG_MIPS_64 */1648#else /* SLJIT_MIPS_REV < 2 */1649#if (defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64)1650if (!is_32) {1651FAIL_IF(push_inst(compiler, DSRL32 | T(src) | D(TMP_REG1) | SH_IMM(0), DR(TMP_REG1)));1652FAIL_IF(push_inst(compiler, ORI | SA(0) | TA(OTHER_FLAG) | 0xffff, OTHER_FLAG));1653FAIL_IF(push_inst(compiler, DSLL32 | T(src) | D(dst) | SH_IMM(0), DR(dst)));1654FAIL_IF(push_inst(compiler, DSLL32 | TA(OTHER_FLAG) | DA(OTHER_FLAG) | SH_IMM(0), OTHER_FLAG));1655FAIL_IF(push_inst(compiler, OR | S(dst) | T(TMP_REG1) | D(dst), DR(dst)));16561657FAIL_IF(push_inst(compiler, DSRL | T(dst) | D(TMP_REG1) | SH_IMM(16), DR(TMP_REG1)));1658FAIL_IF(push_inst(compiler, ORI | SA(OTHER_FLAG) | TA(OTHER_FLAG) | 0xffff, OTHER_FLAG));1659FAIL_IF(push_inst(compiler, AND | S(dst) | TA(OTHER_FLAG) | D(dst), DR(dst)));1660FAIL_IF(push_inst(compiler, AND | S(TMP_REG1) | TA(OTHER_FLAG) | D(TMP_REG1), DR(TMP_REG1)));1661FAIL_IF(push_inst(compiler, DSLL | TA(OTHER_FLAG) | DA(EQUAL_FLAG) | SH_IMM(8), EQUAL_FLAG));1662FAIL_IF(push_inst(compiler, DSLL | T(dst) | D(dst) | SH_IMM(16), DR(dst)));1663FAIL_IF(push_inst(compiler, XOR | SA(OTHER_FLAG) | TA(EQUAL_FLAG) | DA(OTHER_FLAG), OTHER_FLAG));1664FAIL_IF(push_inst(compiler, OR | S(dst) | T(TMP_REG1) | D(dst), DR(dst)));16651666FAIL_IF(push_inst(compiler, DSRL | T(dst) | D(TMP_REG1) | SH_IMM(8), DR(TMP_REG1)));1667FAIL_IF(push_inst(compiler, AND | S(dst) | TA(OTHER_FLAG) | D(dst), DR(dst)));1668FAIL_IF(push_inst(compiler, AND | S(TMP_REG1) | TA(OTHER_FLAG) | D(TMP_REG1), DR(TMP_REG1)));1669FAIL_IF(push_inst(compiler, DSLL | T(dst) | D(dst) | SH_IMM(8), DR(dst)));1670return push_inst(compiler, OR | S(dst) | T(TMP_REG1) | D(dst), DR(dst));1671}16721673if (op != SLJIT_REV && src != TMP_REG2) {1674FAIL_IF(push_inst(compiler, SLL | T(src) | D(TMP_REG2) | SH_IMM(0), DR(TMP_REG2)));1675src = TMP_REG2;1676}1677#endif /* SLJIT_CONFIG_MIPS_64 */16781679FAIL_IF(push_inst(compiler, SRL | T(src) | D(TMP_REG1) | SH_IMM(16), DR(TMP_REG1)));1680FAIL_IF(push_inst(compiler, LUI | TA(OTHER_FLAG) | 0xff, OTHER_FLAG));1681FAIL_IF(push_inst(compiler, SLL | T(src) | D(dst) | SH_IMM(16), DR(dst)));1682FAIL_IF(push_inst(compiler, ORI | SA(OTHER_FLAG) | TA(OTHER_FLAG) | 0xff, OTHER_FLAG));1683FAIL_IF(push_inst(compiler, OR | S(dst) | T(TMP_REG1) | D(dst), DR(dst)));16841685FAIL_IF(push_inst(compiler, SRL | T(dst) | D(TMP_REG1) | SH_IMM(8), DR(TMP_REG1)));1686FAIL_IF(push_inst(compiler, AND | S(dst) | TA(OTHER_FLAG) | D(dst), DR(dst)));1687FAIL_IF(push_inst(compiler, AND | S(TMP_REG1) | TA(OTHER_FLAG) | D(TMP_REG1), DR(TMP_REG1)));1688FAIL_IF(push_inst(compiler, SLL | T(dst) | D(dst) | SH_IMM(8), DR(dst)));1689FAIL_IF(push_inst(compiler, OR | S(dst) | T(TMP_REG1) | D(dst), DR(dst)));16901691#if (defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64)1692if (op == SLJIT_REV_U32 && dst != TMP_REG2 && dst != TMP_REG3) {1693FAIL_IF(push_inst(compiler, DSLL32 | T(dst) | D(dst) | SH_IMM(0), DR(dst)));1694FAIL_IF(push_inst(compiler, DSRL32 | T(dst) | D(dst) | SH_IMM(0), DR(dst)));1695}1696#endif /* SLJIT_CONFIG_MIPS_64 */1697#endif /* SLJIT_MIPR_REV >= 2 */1698return SLJIT_SUCCESS;1699}17001701static sljit_s32 emit_rev16(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 dst, sljit_sw src)1702{1703#if defined(SLJIT_MIPS_REV) && SLJIT_MIPS_REV >= 21704#if defined(SLJIT_CONFIG_MIPS_32) && SLJIT_CONFIG_MIPS_321705FAIL_IF(push_inst(compiler, WSBH | T(src) | D(dst), DR(dst)));1706#else /* !SLJIT_CONFIG_MIPS_32 */1707FAIL_IF(push_inst(compiler, DSBH | T(src) | D(dst), DR(dst)));1708#endif /* SLJIT_CONFIG_MIPS_32 */1709if (GET_OPCODE(op) == SLJIT_REV_U16)1710return push_inst(compiler, ANDI | S(dst) | T(dst) | 0xffff, DR(dst));1711else1712return push_inst(compiler, SEH | T(dst) | D(dst), DR(dst));1713#else /* SLJIT_MIPS_REV < 2 */1714FAIL_IF(push_inst(compiler, SELECT_OP(DSRL, SRL) | T(src) | D(TMP_REG1) | SH_IMM(8), DR(TMP_REG1)));1715FAIL_IF(push_inst(compiler, SELECT_OP(DSLL32, SLL) | T(src) | D(dst) | SH_IMM(24), DR(dst)));1716FAIL_IF(push_inst(compiler, ANDI | S(TMP_REG1) | T(TMP_REG1) | 0xff, DR(TMP_REG1)));1717FAIL_IF(push_inst(compiler, (GET_OPCODE(op) == SLJIT_REV_U16 ? SELECT_OP(DSRL32, SRL) : SELECT_OP(DSRA32, SRA)) | T(dst) | D(dst) | SH_IMM(16), DR(dst)));1718return push_inst(compiler, OR | S(dst) | T(TMP_REG1) | D(dst), DR(dst));1719#endif /* SLJIT_MIPS_REV >= 2 */1720}17211722static SLJIT_INLINE sljit_s32 emit_single_op(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 flags,1723sljit_s32 dst, sljit_s32 src1, sljit_sw src2)1724{1725sljit_s32 is_overflow, is_carry, carry_src_ar, is_handled, reg;1726sljit_ins op_imm, op_v;1727#if (defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64)1728sljit_ins ins, op_dimm, op_dimm32, op_dv;1729#endif17301731switch (GET_OPCODE(op)) {1732case SLJIT_MOV:1733SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & SRC2_IMM));1734if (dst != src2)1735return push_inst(compiler, SELECT_OP(DADDU, ADDU) | S(src2) | TA(0) | D(dst), DR(dst));1736return SLJIT_SUCCESS;17371738case SLJIT_MOV_U8:1739SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & SRC2_IMM));1740if ((flags & (REG_DEST | REG2_SOURCE)) == (REG_DEST | REG2_SOURCE))1741return push_inst(compiler, ANDI | S(src2) | T(dst) | IMM(0xff), DR(dst));1742SLJIT_ASSERT(dst == src2);1743return SLJIT_SUCCESS;17441745case SLJIT_MOV_S8:1746SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & SRC2_IMM));1747if ((flags & (REG_DEST | REG2_SOURCE)) == (REG_DEST | REG2_SOURCE)) {1748#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)1749#if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 2)1750return push_inst(compiler, SEB | T(src2) | D(dst), DR(dst));1751#else /* SLJIT_MIPS_REV < 2 */1752FAIL_IF(push_inst(compiler, SLL | T(src2) | D(dst) | SH_IMM(24), DR(dst)));1753return push_inst(compiler, SRA | T(dst) | D(dst) | SH_IMM(24), DR(dst));1754#endif /* SLJIT_MIPS_REV >= 2 */1755#else /* !SLJIT_CONFIG_MIPS_32 */1756#if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 2)1757if (op & SLJIT_32)1758return push_inst(compiler, SEB | T(src2) | D(dst), DR(dst));1759#endif /* SLJIT_MIPS_REV >= 2 */1760FAIL_IF(push_inst(compiler, DSLL32 | T(src2) | D(dst) | SH_IMM(24), DR(dst)));1761return push_inst(compiler, DSRA32 | T(dst) | D(dst) | SH_IMM(24), DR(dst));1762#endif /* SLJIT_CONFIG_MIPS_32 */1763}1764SLJIT_ASSERT(dst == src2);1765return SLJIT_SUCCESS;17661767case SLJIT_MOV_U16:1768SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & SRC2_IMM));1769if ((flags & (REG_DEST | REG2_SOURCE)) == (REG_DEST | REG2_SOURCE))1770return push_inst(compiler, ANDI | S(src2) | T(dst) | IMM(0xffff), DR(dst));1771SLJIT_ASSERT(dst == src2);1772return SLJIT_SUCCESS;17731774case SLJIT_MOV_S16:1775SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & SRC2_IMM));1776if ((flags & (REG_DEST | REG2_SOURCE)) == (REG_DEST | REG2_SOURCE)) {1777#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)1778#if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 2)1779return push_inst(compiler, SEH | T(src2) | D(dst), DR(dst));1780#else /* SLJIT_MIPS_REV < 2 */1781FAIL_IF(push_inst(compiler, SLL | T(src2) | D(dst) | SH_IMM(16), DR(dst)));1782return push_inst(compiler, SRA | T(dst) | D(dst) | SH_IMM(16), DR(dst));1783#endif /* SLJIT_MIPS_REV >= 2 */1784#else /* !SLJIT_CONFIG_MIPS_32 */1785#if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 2)1786if (op & SLJIT_32)1787return push_inst(compiler, SEH | T(src2) | D(dst), DR(dst));1788#endif /* SLJIT_MIPS_REV >= 2 */1789FAIL_IF(push_inst(compiler, DSLL32 | T(src2) | D(dst) | SH_IMM(16), DR(dst)));1790return push_inst(compiler, DSRA32 | T(dst) | D(dst) | SH_IMM(16), DR(dst));1791#endif /* SLJIT_CONFIG_MIPS_32 */1792}1793SLJIT_ASSERT(dst == src2);1794return SLJIT_SUCCESS;17951796#if (defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64)1797case SLJIT_MOV_U32:1798SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & SRC2_IMM) && !(op & SLJIT_32));1799if ((flags & (REG_DEST | REG2_SOURCE)) == (REG_DEST | REG2_SOURCE)) {1800#if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 2)1801if (dst == src2)1802return push_inst(compiler, DINSU | T(src2) | SA(0) | (31 << 11), DR(dst));1803#endif /* SLJIT_MIPS_REV >= 2 */1804FAIL_IF(push_inst(compiler, DSLL32 | T(src2) | D(dst) | SH_IMM(0), DR(dst)));1805return push_inst(compiler, DSRL32 | T(dst) | D(dst) | SH_IMM(0), DR(dst));1806}1807SLJIT_ASSERT(dst == src2);1808return SLJIT_SUCCESS;18091810case SLJIT_MOV_S32:1811SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & SRC2_IMM) && !(op & SLJIT_32));1812if ((flags & (REG_DEST | REG2_SOURCE)) == (REG_DEST | REG2_SOURCE)) {1813return push_inst(compiler, SLL | T(src2) | D(dst) | SH_IMM(0), DR(dst));1814}1815SLJIT_ASSERT(dst == src2);1816return SLJIT_SUCCESS;1817#endif /* SLJIT_CONFIG_MIPS_64 */18181819#if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 1)1820case SLJIT_CLZ:1821SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & SRC2_IMM));1822#if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 6)1823return push_inst(compiler, SELECT_OP(DCLZ, CLZ) | S(src2) | D(dst), DR(dst));1824#else /* SLJIT_MIPS_REV < 6 */1825return push_inst(compiler, SELECT_OP(DCLZ, CLZ) | S(src2) | T(dst) | D(dst), DR(dst));1826#endif /* SLJIT_MIPS_REV >= 6 */1827case SLJIT_CTZ:1828SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & SRC2_IMM));1829FAIL_IF(push_inst(compiler, SELECT_OP(DSUBU, SUBU) | SA(0) | T(src2) | D(TMP_REG1), DR(TMP_REG1)));1830FAIL_IF(push_inst(compiler, AND | S(src2) | T(TMP_REG1) | D(dst), DR(dst)));1831#if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 6)1832FAIL_IF(push_inst(compiler, SELECT_OP(DCLZ, CLZ) | S(dst) | D(dst), DR(dst)));1833#else /* SLJIT_MIPS_REV < 6 */1834FAIL_IF(push_inst(compiler, SELECT_OP(DCLZ, CLZ) | S(dst) | T(dst) | D(dst), DR(dst)));1835#endif /* SLJIT_MIPS_REV >= 6 */1836FAIL_IF(push_inst(compiler, SELECT_OP(DADDIU, ADDIU) | S(dst) | T(TMP_REG1) | IMM(SELECT_OP(-64, -32)), DR(TMP_REG1)));1837FAIL_IF(push_inst(compiler, SELECT_OP(DSRL32, SRL) | T(TMP_REG1) | D(TMP_REG1) | SH_IMM(SELECT_OP(26, 27)), DR(TMP_REG1)));1838return push_inst(compiler, XOR | S(dst) | T(TMP_REG1) | D(dst), DR(dst));1839#else /* SLJIT_MIPS_REV < 1 */1840case SLJIT_CLZ:1841case SLJIT_CTZ:1842SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & SRC2_IMM));1843return emit_clz_ctz(compiler, op, dst, src2);1844#endif /* SLJIT_MIPS_REV >= 1 */18451846case SLJIT_REV:1847case SLJIT_REV_U32:1848case SLJIT_REV_S32:1849SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & SRC2_IMM) && src2 != TMP_REG1 && dst != TMP_REG1);1850return emit_rev(compiler, op, dst, src2);18511852case SLJIT_REV_U16:1853case SLJIT_REV_S16:1854SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & SRC2_IMM));1855return emit_rev16(compiler, op, dst, src2);18561857case SLJIT_ADD:1858/* Overflow computation (both add and sub): overflow = src1_sign ^ src2_sign ^ result_sign ^ carry_flag */1859is_overflow = GET_FLAG_TYPE(op) == SLJIT_OVERFLOW;1860carry_src_ar = GET_FLAG_TYPE(op) == SLJIT_CARRY;18611862if (flags & SRC2_IMM) {1863if (is_overflow) {1864if (src2 >= 0)1865FAIL_IF(push_inst(compiler, OR | S(src1) | T(src1) | DA(EQUAL_FLAG), EQUAL_FLAG));1866else1867FAIL_IF(push_inst(compiler, NOR | S(src1) | T(src1) | DA(EQUAL_FLAG), EQUAL_FLAG));1868}1869else if (op & SLJIT_SET_Z)1870FAIL_IF(push_inst(compiler, SELECT_OP(DADDIU, ADDIU) | S(src1) | TA(EQUAL_FLAG) | IMM(src2), EQUAL_FLAG));18711872/* Only the zero flag is needed. */1873if (!(flags & UNUSED_DEST) || (op & VARIABLE_FLAG_MASK))1874FAIL_IF(push_inst(compiler, SELECT_OP(DADDIU, ADDIU) | S(src1) | T(dst) | IMM(src2), DR(dst)));1875}1876else {1877if (is_overflow)1878FAIL_IF(push_inst(compiler, XOR | S(src1) | T(src2) | DA(EQUAL_FLAG), EQUAL_FLAG));1879else if (op & SLJIT_SET_Z)1880FAIL_IF(push_inst(compiler, SELECT_OP(DADDU, ADDU) | S(src1) | T(src2) | DA(EQUAL_FLAG), EQUAL_FLAG));18811882if (is_overflow || carry_src_ar != 0) {1883if (src1 != dst)1884carry_src_ar = DR(src1);1885else if (src2 != dst)1886carry_src_ar = DR(src2);1887else {1888FAIL_IF(push_inst(compiler, SELECT_OP(DADDU, ADDU) | S(src1) | TA(0) | DA(OTHER_FLAG), OTHER_FLAG));1889carry_src_ar = OTHER_FLAG;1890}1891}18921893/* Only the zero flag is needed. */1894if (!(flags & UNUSED_DEST) || (op & VARIABLE_FLAG_MASK))1895FAIL_IF(push_inst(compiler, SELECT_OP(DADDU, ADDU) | S(src1) | T(src2) | D(dst), DR(dst)));1896}18971898/* Carry is zero if a + b >= a or a + b >= b, otherwise it is 1. */1899if (is_overflow || carry_src_ar != 0) {1900if (flags & SRC2_IMM)1901FAIL_IF(push_inst(compiler, SLTIU | S(dst) | TA(OTHER_FLAG) | IMM(src2), OTHER_FLAG));1902else1903FAIL_IF(push_inst(compiler, SLTU | S(dst) | TA(carry_src_ar) | DA(OTHER_FLAG), OTHER_FLAG));1904}19051906if (!is_overflow)1907return SLJIT_SUCCESS;19081909FAIL_IF(push_inst(compiler, XOR | S(dst) | TA(EQUAL_FLAG) | D(TMP_REG1), DR(TMP_REG1)));1910if (op & SLJIT_SET_Z)1911FAIL_IF(push_inst(compiler, SELECT_OP(DADDU, ADDU) | S(dst) | TA(0) | DA(EQUAL_FLAG), EQUAL_FLAG));1912FAIL_IF(push_inst(compiler, SELECT_OP(DSRL32, SRL) | T(TMP_REG1) | D(TMP_REG1) | SH_IMM(31), DR(TMP_REG1)));1913return push_inst(compiler, XOR | S(TMP_REG1) | TA(OTHER_FLAG) | DA(OTHER_FLAG), OTHER_FLAG);19141915case SLJIT_ADDC:1916carry_src_ar = GET_FLAG_TYPE(op) == SLJIT_CARRY;19171918if (flags & SRC2_IMM) {1919FAIL_IF(push_inst(compiler, SELECT_OP(DADDIU, ADDIU) | S(src1) | T(dst) | IMM(src2), DR(dst)));1920} else {1921if (carry_src_ar != 0) {1922if (src1 != dst)1923carry_src_ar = DR(src1);1924else if (src2 != dst)1925carry_src_ar = DR(src2);1926else {1927FAIL_IF(push_inst(compiler, SELECT_OP(DADDU, ADDU) | S(src1) | TA(0) | DA(EQUAL_FLAG), EQUAL_FLAG));1928carry_src_ar = EQUAL_FLAG;1929}1930}19311932FAIL_IF(push_inst(compiler, SELECT_OP(DADDU, ADDU) | S(src1) | T(src2) | D(dst), DR(dst)));1933}19341935/* Carry is zero if a + b >= a or a + b >= b, otherwise it is 1. */1936if (carry_src_ar != 0) {1937if (flags & SRC2_IMM)1938FAIL_IF(push_inst(compiler, SLTIU | S(dst) | TA(EQUAL_FLAG) | IMM(src2), EQUAL_FLAG));1939else1940FAIL_IF(push_inst(compiler, SLTU | S(dst) | TA(carry_src_ar) | DA(EQUAL_FLAG), EQUAL_FLAG));1941}19421943FAIL_IF(push_inst(compiler, SELECT_OP(DADDU, ADDU) | S(dst) | TA(OTHER_FLAG) | D(dst), DR(dst)));19441945if (carry_src_ar == 0)1946return SLJIT_SUCCESS;19471948/* Set ULESS_FLAG (dst == 0) && (OTHER_FLAG == 1). */1949FAIL_IF(push_inst(compiler, SLTU | S(dst) | TA(OTHER_FLAG) | DA(OTHER_FLAG), OTHER_FLAG));1950/* Set carry flag. */1951return push_inst(compiler, OR | SA(OTHER_FLAG) | TA(EQUAL_FLAG) | DA(OTHER_FLAG), OTHER_FLAG);19521953case SLJIT_SUB:1954if ((flags & SRC2_IMM) && src2 == SIMM_MIN) {1955FAIL_IF(push_inst(compiler, ADDIU | SA(0) | T(TMP_REG2) | IMM(src2), DR(TMP_REG2)));1956src2 = TMP_REG2;1957flags &= ~SRC2_IMM;1958}19591960is_handled = 0;19611962if (flags & SRC2_IMM) {1963if (GET_FLAG_TYPE(op) == SLJIT_LESS) {1964FAIL_IF(push_inst(compiler, SLTIU | S(src1) | TA(OTHER_FLAG) | IMM(src2), OTHER_FLAG));1965is_handled = 1;1966}1967else if (GET_FLAG_TYPE(op) == SLJIT_SIG_LESS) {1968FAIL_IF(push_inst(compiler, SLTI | S(src1) | TA(OTHER_FLAG) | IMM(src2), OTHER_FLAG));1969is_handled = 1;1970}1971}19721973if (!is_handled && GET_FLAG_TYPE(op) >= SLJIT_LESS && GET_FLAG_TYPE(op) <= SLJIT_SIG_LESS_EQUAL) {1974is_handled = 1;19751976if (flags & SRC2_IMM) {1977reg = (src1 == TMP_REG1) ? TMP_REG2 : TMP_REG1;1978FAIL_IF(push_inst(compiler, ADDIU | SA(0) | T(reg) | IMM(src2), DR(reg)));1979src2 = reg;1980flags &= ~SRC2_IMM;1981}19821983switch (GET_FLAG_TYPE(op)) {1984case SLJIT_LESS:1985FAIL_IF(push_inst(compiler, SLTU | S(src1) | T(src2) | DA(OTHER_FLAG), OTHER_FLAG));1986break;1987case SLJIT_GREATER:1988FAIL_IF(push_inst(compiler, SLTU | S(src2) | T(src1) | DA(OTHER_FLAG), OTHER_FLAG));1989break;1990case SLJIT_SIG_LESS:1991FAIL_IF(push_inst(compiler, SLT | S(src1) | T(src2) | DA(OTHER_FLAG), OTHER_FLAG));1992break;1993case SLJIT_SIG_GREATER:1994FAIL_IF(push_inst(compiler, SLT | S(src2) | T(src1) | DA(OTHER_FLAG), OTHER_FLAG));1995break;1996}1997}19981999if (is_handled) {2000if (flags & SRC2_IMM) {2001if (op & SLJIT_SET_Z)2002FAIL_IF(push_inst(compiler, SELECT_OP(DADDIU, ADDIU) | S(src1) | TA(EQUAL_FLAG) | IMM(-src2), EQUAL_FLAG));2003if (!(flags & UNUSED_DEST))2004return push_inst(compiler, SELECT_OP(DADDIU, ADDIU) | S(src1) | T(dst) | IMM(-src2), DR(dst));2005}2006else {2007if (op & SLJIT_SET_Z)2008FAIL_IF(push_inst(compiler, SELECT_OP(DSUBU, SUBU) | S(src1) | T(src2) | DA(EQUAL_FLAG), EQUAL_FLAG));2009if (!(flags & UNUSED_DEST))2010return push_inst(compiler, SELECT_OP(DSUBU, SUBU) | S(src1) | T(src2) | D(dst), DR(dst));2011}2012return SLJIT_SUCCESS;2013}20142015is_overflow = GET_FLAG_TYPE(op) == SLJIT_OVERFLOW;2016is_carry = GET_FLAG_TYPE(op) == SLJIT_CARRY;20172018if (flags & SRC2_IMM) {2019if (is_overflow) {2020if (src2 >= 0)2021FAIL_IF(push_inst(compiler, OR | S(src1) | T(src1) | DA(EQUAL_FLAG), EQUAL_FLAG));2022else2023FAIL_IF(push_inst(compiler, NOR | S(src1) | T(src1) | DA(EQUAL_FLAG), EQUAL_FLAG));2024}2025else if (op & SLJIT_SET_Z)2026FAIL_IF(push_inst(compiler, SELECT_OP(DADDIU, ADDIU) | S(src1) | TA(EQUAL_FLAG) | IMM(-src2), EQUAL_FLAG));20272028if (is_overflow || is_carry)2029FAIL_IF(push_inst(compiler, SLTIU | S(src1) | TA(OTHER_FLAG) | IMM(src2), OTHER_FLAG));20302031/* Only the zero flag is needed. */2032if (!(flags & UNUSED_DEST) || (op & VARIABLE_FLAG_MASK))2033FAIL_IF(push_inst(compiler, SELECT_OP(DADDIU, ADDIU) | S(src1) | T(dst) | IMM(-src2), DR(dst)));2034}2035else {2036if (is_overflow)2037FAIL_IF(push_inst(compiler, XOR | S(src1) | T(src2) | DA(EQUAL_FLAG), EQUAL_FLAG));2038else if (op & SLJIT_SET_Z)2039FAIL_IF(push_inst(compiler, SELECT_OP(DSUBU, SUBU) | S(src1) | T(src2) | DA(EQUAL_FLAG), EQUAL_FLAG));20402041if (is_overflow || is_carry)2042FAIL_IF(push_inst(compiler, SLTU | S(src1) | T(src2) | DA(OTHER_FLAG), OTHER_FLAG));20432044/* Only the zero flag is needed. */2045if (!(flags & UNUSED_DEST) || (op & VARIABLE_FLAG_MASK))2046FAIL_IF(push_inst(compiler, SELECT_OP(DSUBU, SUBU) | S(src1) | T(src2) | D(dst), DR(dst)));2047}20482049if (!is_overflow)2050return SLJIT_SUCCESS;20512052FAIL_IF(push_inst(compiler, XOR | S(dst) | TA(EQUAL_FLAG) | D(TMP_REG1), DR(TMP_REG1)));2053if (op & SLJIT_SET_Z)2054FAIL_IF(push_inst(compiler, SELECT_OP(DADDU, ADDU) | S(dst) | TA(0) | DA(EQUAL_FLAG), EQUAL_FLAG));2055FAIL_IF(push_inst(compiler, SELECT_OP(DSRL32, SRL) | T(TMP_REG1) | D(TMP_REG1) | SH_IMM(31), DR(TMP_REG1)));2056return push_inst(compiler, XOR | S(TMP_REG1) | TA(OTHER_FLAG) | DA(OTHER_FLAG), OTHER_FLAG);20572058case SLJIT_SUBC:2059if ((flags & SRC2_IMM) && src2 == SIMM_MIN) {2060FAIL_IF(push_inst(compiler, ADDIU | SA(0) | T(TMP_REG2) | IMM(src2), DR(TMP_REG2)));2061src2 = TMP_REG2;2062flags &= ~SRC2_IMM;2063}20642065is_carry = GET_FLAG_TYPE(op) == SLJIT_CARRY;20662067if (flags & SRC2_IMM) {2068if (is_carry)2069FAIL_IF(push_inst(compiler, SLTIU | S(src1) | TA(EQUAL_FLAG) | IMM(src2), EQUAL_FLAG));20702071FAIL_IF(push_inst(compiler, SELECT_OP(DADDIU, ADDIU) | S(src1) | T(dst) | IMM(-src2), DR(dst)));2072}2073else {2074if (is_carry)2075FAIL_IF(push_inst(compiler, SLTU | S(src1) | T(src2) | DA(EQUAL_FLAG), EQUAL_FLAG));20762077FAIL_IF(push_inst(compiler, SELECT_OP(DSUBU, SUBU) | S(src1) | T(src2) | D(dst), DR(dst)));2078}20792080if (is_carry)2081FAIL_IF(push_inst(compiler, SLTU | S(dst) | TA(OTHER_FLAG) | D(TMP_REG1), DR(TMP_REG1)));20822083FAIL_IF(push_inst(compiler, SELECT_OP(DSUBU, SUBU) | S(dst) | TA(OTHER_FLAG) | D(dst), DR(dst)));20842085if (!is_carry)2086return SLJIT_SUCCESS;20872088return push_inst(compiler, OR | SA(EQUAL_FLAG) | T(TMP_REG1) | DA(OTHER_FLAG), OTHER_FLAG);20892090case SLJIT_MUL:2091SLJIT_ASSERT(!(flags & SRC2_IMM));20922093if (GET_FLAG_TYPE(op) != SLJIT_OVERFLOW) {2094#if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 6)2095return push_inst(compiler, SELECT_OP(DMUL, MUL) | S(src1) | T(src2) | D(dst), DR(dst));2096#elif (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 1)2097#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)2098return push_inst(compiler, MUL | S(src1) | T(src2) | D(dst), DR(dst));2099#else /* !SLJIT_CONFIG_MIPS_32 */2100if (op & SLJIT_32)2101return push_inst(compiler, MUL | S(src1) | T(src2) | D(dst), DR(dst));2102FAIL_IF(push_inst(compiler, DMULT | S(src1) | T(src2), MOVABLE_INS));2103return push_inst(compiler, MFLO | D(dst), DR(dst));2104#endif /* SLJIT_CONFIG_MIPS_32 */2105#else /* SLJIT_MIPS_REV < 1 */2106FAIL_IF(push_inst(compiler, SELECT_OP(DMULT, MULT) | S(src1) | T(src2), MOVABLE_INS));2107return push_inst(compiler, MFLO | D(dst), DR(dst));2108#endif /* SLJIT_MIPS_REV >= 6 */2109}21102111#if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 6)2112FAIL_IF(push_inst(compiler, SELECT_OP(DMUL, MUL) | S(src1) | T(src2) | D(dst), DR(dst)));2113FAIL_IF(push_inst(compiler, SELECT_OP(DMUH, MUH) | S(src1) | T(src2) | DA(EQUAL_FLAG), EQUAL_FLAG));2114#else /* SLJIT_MIPS_REV < 6 */2115FAIL_IF(push_inst(compiler, SELECT_OP(DMULT, MULT) | S(src1) | T(src2), MOVABLE_INS));2116FAIL_IF(push_inst(compiler, MFHI | DA(EQUAL_FLAG), EQUAL_FLAG));2117FAIL_IF(push_inst(compiler, MFLO | D(dst), DR(dst)));2118#endif /* SLJIT_MIPS_REV >= 6 */2119FAIL_IF(push_inst(compiler, SELECT_OP(DSRA32, SRA) | T(dst) | DA(OTHER_FLAG) | SH_IMM(31), OTHER_FLAG));2120return push_inst(compiler, SELECT_OP(DSUBU, SUBU) | SA(EQUAL_FLAG) | TA(OTHER_FLAG) | DA(OTHER_FLAG), OTHER_FLAG);21212122case SLJIT_AND:2123EMIT_LOGICAL(ANDI, AND);2124return SLJIT_SUCCESS;21252126case SLJIT_OR:2127EMIT_LOGICAL(ORI, OR);2128return SLJIT_SUCCESS;21292130case SLJIT_XOR:2131if (!(flags & LOGICAL_OP)) {2132SLJIT_ASSERT((flags & SRC2_IMM) && src2 == -1);2133if (op & SLJIT_SET_Z)2134FAIL_IF(push_inst(compiler, NOR | S(src1) | T(src1) | DA(EQUAL_FLAG), EQUAL_FLAG));2135if (!(flags & UNUSED_DEST))2136FAIL_IF(push_inst(compiler, NOR | S(src1) | T(src1) | D(dst), DR(dst)));2137return SLJIT_SUCCESS;2138}2139EMIT_LOGICAL(XORI, XOR);2140return SLJIT_SUCCESS;21412142case SLJIT_SHL:2143case SLJIT_MSHL:2144EMIT_SHIFT(DSLL, DSLL32, SLL, DSLLV, SLLV);2145break;21462147case SLJIT_LSHR:2148case SLJIT_MLSHR:2149EMIT_SHIFT(DSRL, DSRL32, SRL, DSRLV, SRLV);2150break;21512152case SLJIT_ASHR:2153case SLJIT_MASHR:2154EMIT_SHIFT(DSRA, DSRA32, SRA, DSRAV, SRAV);2155break;21562157#if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 2)2158case SLJIT_ROTL:2159if ((flags & SRC2_IMM) || src2 == 0) {2160#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)2161src2 = -src2 & 0x1f;2162#else /* !SLJIT_CONFIG_MIPS_32 */2163src2 = -src2 & ((op & SLJIT_32) ? 0x1f : 0x3f);2164#endif /* SLJIT_CONFIG_MIPS_32 */2165} else {2166FAIL_IF(push_inst(compiler, SELECT_OP(DSUBU, SUBU) | SA(0) | T(src2) | D(TMP_REG2), DR(TMP_REG2)));2167src2 = TMP_REG2;2168}2169/* fallthrough */21702171case SLJIT_ROTR:2172EMIT_SHIFT(DROTR, DROTR32, ROTR, DROTRV, ROTRV);2173break;2174#else /* SLJIT_MIPS_REV < 1 */2175case SLJIT_ROTL:2176case SLJIT_ROTR:2177if (flags & SRC2_IMM) {2178SLJIT_ASSERT(src2 != 0);2179#if (defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64)2180if (!(op & SLJIT_32)) {2181if (GET_OPCODE(op) == SLJIT_ROTL)2182op_imm = ((src2 < 32) ? DSLL : DSLL32);2183else2184op_imm = ((src2 < 32) ? DSRL : DSRL32);21852186FAIL_IF(push_inst(compiler, op_imm | T(src1) | DA(OTHER_FLAG) | (((sljit_ins)src2 & 0x1f) << 6), OTHER_FLAG));21872188src2 = 64 - src2;2189if (GET_OPCODE(op) == SLJIT_ROTL)2190op_imm = ((src2 < 32) ? DSRL : DSRL32);2191else2192op_imm = ((src2 < 32) ? DSLL : DSLL32);21932194FAIL_IF(push_inst(compiler, op_imm | T(src1) | D(dst) | (((sljit_ins)src2 & 0x1f) << 6), DR(dst)));2195return push_inst(compiler, OR | S(dst) | TA(OTHER_FLAG) | D(dst), DR(dst));2196}2197#endif /* SLJIT_CONFIG_MIPS_64 */21982199op_imm = (GET_OPCODE(op) == SLJIT_ROTL) ? SLL : SRL;2200FAIL_IF(push_inst(compiler, op_imm | T(src1) | DA(OTHER_FLAG) | ((sljit_ins)src2 << 6), OTHER_FLAG));22012202src2 = 32 - src2;2203op_imm = (GET_OPCODE(op) == SLJIT_ROTL) ? SRL : SLL;2204FAIL_IF(push_inst(compiler, op_imm | T(src1) | D(dst) | (((sljit_ins)src2 & 0x1f) << 6), DR(dst)));2205return push_inst(compiler, OR | S(dst) | TA(OTHER_FLAG) | D(dst), DR(dst));2206}22072208if (src2 == 0) {2209if (dst != src1)2210return push_inst(compiler, SELECT_OP(DADDU, ADDU) | S(src1) | TA(0) | D(dst), DR(dst));2211return SLJIT_SUCCESS;2212}22132214FAIL_IF(push_inst(compiler, SELECT_OP(DSUBU, SUBU) | SA(0) | T(src2) | DA(EQUAL_FLAG), EQUAL_FLAG));22152216#if (defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64)2217if (!(op & SLJIT_32)) {2218op_v = (GET_OPCODE(op) == SLJIT_ROTL) ? DSLLV : DSRLV;2219FAIL_IF(push_inst(compiler, op_v | S(src2) | T(src1) | DA(OTHER_FLAG), OTHER_FLAG));2220op_v = (GET_OPCODE(op) == SLJIT_ROTL) ? DSRLV : DSLLV;2221FAIL_IF(push_inst(compiler, op_v | SA(EQUAL_FLAG) | T(src1) | D(dst), DR(dst)));2222return push_inst(compiler, OR | S(dst) | TA(OTHER_FLAG) | D(dst), DR(dst));2223}2224#endif /* SLJIT_CONFIG_MIPS_64 */22252226op_v = (GET_OPCODE(op) == SLJIT_ROTL) ? SLLV : SRLV;2227FAIL_IF(push_inst(compiler, op_v | S(src2) | T(src1) | DA(OTHER_FLAG), OTHER_FLAG));2228op_v = (GET_OPCODE(op) == SLJIT_ROTL) ? SRLV : SLLV;2229FAIL_IF(push_inst(compiler, op_v | SA(EQUAL_FLAG) | T(src1) | D(dst), DR(dst)));2230return push_inst(compiler, OR | S(dst) | TA(OTHER_FLAG) | D(dst), DR(dst));2231#endif /* SLJIT_MIPS_REV >= 2 */22322233default:2234SLJIT_UNREACHABLE();2235return SLJIT_SUCCESS;2236}22372238#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)2239if ((flags & SRC2_IMM) || src2 == 0) {2240if (op & SLJIT_SET_Z)2241FAIL_IF(push_inst(compiler, op_imm | T(src1) | DA(EQUAL_FLAG) | SH_IMM(src2), EQUAL_FLAG));22422243if (flags & UNUSED_DEST)2244return SLJIT_SUCCESS;2245return push_inst(compiler, op_imm | T(src1) | D(dst) | SH_IMM(src2), DR(dst));2246}22472248if (op & SLJIT_SET_Z)2249FAIL_IF(push_inst(compiler, op_v | S(src2) | T(src1) | DA(EQUAL_FLAG), EQUAL_FLAG));22502251if (flags & UNUSED_DEST)2252return SLJIT_SUCCESS;2253return push_inst(compiler, op_v | S(src2) | T(src1) | D(dst), DR(dst));2254#else /* !SLJIT_CONFIG_MIPS_32 */2255if ((flags & SRC2_IMM) || src2 == 0) {2256if (src2 >= 32) {2257SLJIT_ASSERT(!(op & SLJIT_32));2258ins = op_dimm32;2259src2 -= 32;2260}2261else2262ins = (op & SLJIT_32) ? op_imm : op_dimm;22632264if (op & SLJIT_SET_Z)2265FAIL_IF(push_inst(compiler, ins | T(src1) | DA(EQUAL_FLAG) | SH_IMM(src2), EQUAL_FLAG));22662267if (flags & UNUSED_DEST)2268return SLJIT_SUCCESS;2269return push_inst(compiler, ins | T(src1) | D(dst) | SH_IMM(src2), DR(dst));2270}22712272ins = (op & SLJIT_32) ? op_v : op_dv;2273if (op & SLJIT_SET_Z)2274FAIL_IF(push_inst(compiler, ins | S(src2) | T(src1) | DA(EQUAL_FLAG), EQUAL_FLAG));22752276if (flags & UNUSED_DEST)2277return SLJIT_SUCCESS;2278return push_inst(compiler, ins | S(src2) | T(src1) | D(dst), DR(dst));2279#endif /* SLJIT_CONFIG_MIPS_32 */2280}22812282#define CHECK_IMM(flags, srcw) \2283((!((flags) & LOGICAL_OP) && ((srcw) <= SIMM_MAX && (srcw) >= SIMM_MIN)) \2284|| (((flags) & LOGICAL_OP) && !((srcw) & ~UIMM_MAX)))22852286static sljit_s32 emit_op(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 flags,2287sljit_s32 dst, sljit_sw dstw,2288sljit_s32 src1, sljit_sw src1w,2289sljit_s32 src2, sljit_sw src2w)2290{2291/* arg1 goes to TMP_REG1 or src reg2292arg2 goes to TMP_REG2, imm or src reg2293TMP_REG3 can be used for caching2294result goes to TMP_REG2, so put result can use TMP_REG1 and TMP_REG3. */2295sljit_s32 dst_r = TMP_REG2;2296sljit_s32 src1_r;2297sljit_sw src2_r = 0;2298sljit_s32 src2_tmp_reg = (GET_OPCODE(op) >= SLJIT_OP2_BASE && FAST_IS_REG(src1)) ? TMP_REG1 : TMP_REG2;22992300if (!(flags & ALT_KEEP_CACHE)) {2301compiler->cache_arg = 0;2302compiler->cache_argw = 0;2303}23042305if (dst == 0) {2306SLJIT_ASSERT(HAS_FLAGS(op));2307flags |= UNUSED_DEST;2308dst = TMP_REG2;2309}2310else if (FAST_IS_REG(dst)) {2311dst_r = dst;2312flags |= REG_DEST;2313if (flags & MOVE_OP)2314src2_tmp_reg = dst_r;2315}2316else if ((dst & SLJIT_MEM) && !getput_arg_fast(compiler, flags | ARG_TEST, DR(TMP_REG1), dst, dstw))2317flags |= SLOW_DEST;23182319if (flags & IMM_OP) {2320if (src2 == SLJIT_IMM && src2w != 0 && CHECK_IMM(flags, src2w)) {2321flags |= SRC2_IMM;2322src2_r = src2w;2323} else if ((flags & CUMULATIVE_OP) && src1 == SLJIT_IMM && src1w != 0 && CHECK_IMM(flags, src1w)) {2324flags |= SRC2_IMM;2325src2_r = src1w;23262327/* And swap arguments. */2328src1 = src2;2329src1w = src2w;2330src2 = SLJIT_IMM;2331/* src2w = src2_r unneeded. */2332}2333}23342335/* Source 1. */2336if (FAST_IS_REG(src1)) {2337src1_r = src1;2338flags |= REG1_SOURCE;2339}2340else if (src1 == SLJIT_IMM) {2341if (src1w) {2342FAIL_IF(load_immediate(compiler, DR(TMP_REG1), src1w));2343src1_r = TMP_REG1;2344}2345else2346src1_r = 0;2347}2348else {2349if (getput_arg_fast(compiler, flags | LOAD_DATA, DR(TMP_REG1), src1, src1w))2350FAIL_IF(compiler->error);2351else2352flags |= SLOW_SRC1;2353src1_r = TMP_REG1;2354}23552356/* Source 2. */2357if (FAST_IS_REG(src2)) {2358src2_r = src2;2359flags |= REG2_SOURCE;2360if ((flags & (REG_DEST | MOVE_OP)) == MOVE_OP)2361dst_r = (sljit_s32)src2_r;2362}2363else if (src2 == SLJIT_IMM) {2364if (!(flags & SRC2_IMM)) {2365if (src2w) {2366FAIL_IF(load_immediate(compiler, DR(src2_tmp_reg), src2w));2367src2_r = src2_tmp_reg;2368}2369else {2370src2_r = 0;2371if (flags & MOVE_OP) {2372if (dst & SLJIT_MEM)2373dst_r = 0;2374else2375op = SLJIT_MOV;2376}2377}2378}2379}2380else {2381if (getput_arg_fast(compiler, flags | LOAD_DATA, DR(src2_tmp_reg), src2, src2w))2382FAIL_IF(compiler->error);2383else2384flags |= SLOW_SRC2;2385src2_r = src2_tmp_reg;2386}23872388if ((flags & (SLOW_SRC1 | SLOW_SRC2)) == (SLOW_SRC1 | SLOW_SRC2)) {2389SLJIT_ASSERT(src2_r == TMP_REG2);2390if ((flags & SLOW_DEST) && !can_cache(src1, src1w, src2, src2w) && can_cache(src1, src1w, dst, dstw)) {2391FAIL_IF(getput_arg(compiler, flags | LOAD_DATA, DR(TMP_REG2), src2, src2w, src1, src1w));2392FAIL_IF(getput_arg(compiler, flags | LOAD_DATA, DR(TMP_REG1), src1, src1w, dst, dstw));2393}2394else {2395FAIL_IF(getput_arg(compiler, flags | LOAD_DATA, DR(TMP_REG1), src1, src1w, src2, src2w));2396FAIL_IF(getput_arg(compiler, flags | LOAD_DATA, DR(TMP_REG2), src2, src2w, dst, dstw));2397}2398}2399else if (flags & SLOW_SRC1)2400FAIL_IF(getput_arg(compiler, flags | LOAD_DATA, DR(TMP_REG1), src1, src1w, dst, dstw));2401else if (flags & SLOW_SRC2)2402FAIL_IF(getput_arg(compiler, flags | LOAD_DATA, DR(src2_tmp_reg), src2, src2w, dst, dstw));24032404FAIL_IF(emit_single_op(compiler, op, flags, dst_r, src1_r, src2_r));24052406if (dst & SLJIT_MEM) {2407if (!(flags & SLOW_DEST)) {2408getput_arg_fast(compiler, flags, DR(dst_r), dst, dstw);2409return compiler->error;2410}2411return getput_arg(compiler, flags, DR(dst_r), dst, dstw, 0, 0);2412}24132414return SLJIT_SUCCESS;2415}24162417#undef CHECK_IMM24182419SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op0(struct sljit_compiler *compiler, sljit_s32 op)2420{2421#if (defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64)2422sljit_s32 int_op = op & SLJIT_32;2423#endif24242425CHECK_ERROR();2426CHECK(check_sljit_emit_op0(compiler, op));24272428op = GET_OPCODE(op);2429switch (op) {2430case SLJIT_BREAKPOINT:2431return push_inst(compiler, BREAK, UNMOVABLE_INS);2432case SLJIT_NOP:2433return push_inst(compiler, NOP, UNMOVABLE_INS);2434case SLJIT_LMUL_UW:2435case SLJIT_LMUL_SW:2436#if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 6)2437#if (defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64)2438FAIL_IF(push_inst(compiler, (op == SLJIT_LMUL_UW ? DMULU : DMUL) | S(SLJIT_R0) | T(SLJIT_R1) | D(TMP_REG3), DR(TMP_REG3)));2439FAIL_IF(push_inst(compiler, (op == SLJIT_LMUL_UW ? DMUHU : DMUH) | S(SLJIT_R0) | T(SLJIT_R1) | D(TMP_REG1), DR(TMP_REG1)));2440#else /* !SLJIT_CONFIG_MIPS_64 */2441FAIL_IF(push_inst(compiler, (op == SLJIT_LMUL_UW ? MULU : MUL) | S(SLJIT_R0) | T(SLJIT_R1) | D(TMP_REG3), DR(TMP_REG3)));2442FAIL_IF(push_inst(compiler, (op == SLJIT_LMUL_UW ? MUHU : MUH) | S(SLJIT_R0) | T(SLJIT_R1) | D(TMP_REG1), DR(TMP_REG1)));2443#endif /* SLJIT_CONFIG_MIPS_64 */2444FAIL_IF(push_inst(compiler, ADDU_W | S(TMP_REG3) | TA(0) | D(SLJIT_R0), DR(SLJIT_R0)));2445return push_inst(compiler, ADDU_W | S(TMP_REG1) | TA(0) | D(SLJIT_R1), DR(SLJIT_R1));2446#else /* SLJIT_MIPS_REV < 6 */2447#if (defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64)2448FAIL_IF(push_inst(compiler, (op == SLJIT_LMUL_UW ? DMULTU : DMULT) | S(SLJIT_R0) | T(SLJIT_R1), MOVABLE_INS));2449#else /* !SLJIT_CONFIG_MIPS_64 */2450FAIL_IF(push_inst(compiler, (op == SLJIT_LMUL_UW ? MULTU : MULT) | S(SLJIT_R0) | T(SLJIT_R1), MOVABLE_INS));2451#endif /* SLJIT_CONFIG_MIPS_64 */2452FAIL_IF(push_inst(compiler, MFLO | D(SLJIT_R0), DR(SLJIT_R0)));2453return push_inst(compiler, MFHI | D(SLJIT_R1), DR(SLJIT_R1));2454#endif /* SLJIT_MIPS_REV >= 6 */2455case SLJIT_DIVMOD_UW:2456case SLJIT_DIVMOD_SW:2457case SLJIT_DIV_UW:2458case SLJIT_DIV_SW:2459SLJIT_COMPILE_ASSERT((SLJIT_DIVMOD_UW & 0x2) == 0 && SLJIT_DIV_UW - 0x2 == SLJIT_DIVMOD_UW, bad_div_opcode_assignments);2460#if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 6)2461#if (defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64)2462if (int_op) {2463FAIL_IF(push_inst(compiler, ((op | 0x2) == SLJIT_DIV_UW ? DIVU : DIV) | S(SLJIT_R0) | T(SLJIT_R1) | D(TMP_REG3), DR(TMP_REG3)));2464FAIL_IF(push_inst(compiler, ((op | 0x2) == SLJIT_DIV_UW ? MODU : MOD) | S(SLJIT_R0) | T(SLJIT_R1) | D(TMP_REG1), DR(TMP_REG1)));2465}2466else {2467FAIL_IF(push_inst(compiler, ((op | 0x2) == SLJIT_DIV_UW ? DDIVU : DDIV) | S(SLJIT_R0) | T(SLJIT_R1) | D(TMP_REG3), DR(TMP_REG3)));2468FAIL_IF(push_inst(compiler, ((op | 0x2) == SLJIT_DIV_UW ? DMODU : DMOD) | S(SLJIT_R0) | T(SLJIT_R1) | D(TMP_REG1), DR(TMP_REG1)));2469}2470#else /* !SLJIT_CONFIG_MIPS_64 */2471FAIL_IF(push_inst(compiler, ((op | 0x2) == SLJIT_DIV_UW ? DIVU : DIV) | S(SLJIT_R0) | T(SLJIT_R1) | D(TMP_REG3), DR(TMP_REG3)));2472FAIL_IF(push_inst(compiler, ((op | 0x2) == SLJIT_DIV_UW ? MODU : MOD) | S(SLJIT_R0) | T(SLJIT_R1) | D(TMP_REG1), DR(TMP_REG1)));2473#endif /* SLJIT_CONFIG_MIPS_64 */2474FAIL_IF(push_inst(compiler, ADDU_W | S(TMP_REG3) | TA(0) | D(SLJIT_R0), DR(SLJIT_R0)));2475return (op >= SLJIT_DIV_UW) ? SLJIT_SUCCESS : push_inst(compiler, ADDU_W | S(TMP_REG1) | TA(0) | D(SLJIT_R1), DR(SLJIT_R1));2476#else /* SLJIT_MIPS_REV < 6 */2477#if !(defined SLJIT_MIPS_REV)2478FAIL_IF(push_inst(compiler, NOP, UNMOVABLE_INS));2479FAIL_IF(push_inst(compiler, NOP, UNMOVABLE_INS));2480#endif /* !SLJIT_MIPS_REV */2481#if (defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64)2482if (int_op)2483FAIL_IF(push_inst(compiler, ((op | 0x2) == SLJIT_DIV_UW ? DIVU : DIV) | S(SLJIT_R0) | T(SLJIT_R1), MOVABLE_INS));2484else2485FAIL_IF(push_inst(compiler, ((op | 0x2) == SLJIT_DIV_UW ? DDIVU : DDIV) | S(SLJIT_R0) | T(SLJIT_R1), MOVABLE_INS));2486#else /* !SLJIT_CONFIG_MIPS_64 */2487FAIL_IF(push_inst(compiler, ((op | 0x2) == SLJIT_DIV_UW ? DIVU : DIV) | S(SLJIT_R0) | T(SLJIT_R1), MOVABLE_INS));2488#endif /* SLJIT_CONFIG_MIPS_64 */2489FAIL_IF(push_inst(compiler, MFLO | D(SLJIT_R0), DR(SLJIT_R0)));2490return (op >= SLJIT_DIV_UW) ? SLJIT_SUCCESS : push_inst(compiler, MFHI | D(SLJIT_R1), DR(SLJIT_R1));2491#endif /* SLJIT_MIPS_REV >= 6 */2492case SLJIT_MEMORY_BARRIER:2493#if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 1)2494return push_inst(compiler, SYNC, UNMOVABLE_INS);2495#else /* SLJIT_MIPS_REV < 1 */2496return SLJIT_ERR_UNSUPPORTED;2497#endif /* SLJIT_MIPS_REV >= 1 */2498case SLJIT_ENDBR:2499case SLJIT_SKIP_FRAMES_BEFORE_RETURN:2500return SLJIT_SUCCESS;2501}25022503return SLJIT_SUCCESS;2504}25052506#if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 1)2507static sljit_s32 emit_prefetch(struct sljit_compiler *compiler,2508sljit_s32 src, sljit_sw srcw)2509{2510if (!(src & OFFS_REG_MASK)) {2511if (srcw <= SIMM_MAX && srcw >= SIMM_MIN)2512return push_inst(compiler, PREF | S(src & REG_MASK) | IMM(srcw), MOVABLE_INS);25132514FAIL_IF(load_immediate(compiler, DR(TMP_REG1), srcw));2515return push_inst(compiler, PREFX | S(src & REG_MASK) | T(TMP_REG1), MOVABLE_INS);2516}25172518srcw &= 0x3;25192520if (SLJIT_UNLIKELY(srcw != 0)) {2521FAIL_IF(push_inst(compiler, SLL_W | T(OFFS_REG(src)) | D(TMP_REG1) | SH_IMM(srcw), DR(TMP_REG1)));2522return push_inst(compiler, PREFX | S(src & REG_MASK) | T(TMP_REG1), MOVABLE_INS);2523}25242525return push_inst(compiler, PREFX | S(src & REG_MASK) | T(OFFS_REG(src)), MOVABLE_INS);2526}2527#endif /* SLJIT_MIPS_REV >= 1 */25282529SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op1(struct sljit_compiler *compiler, sljit_s32 op,2530sljit_s32 dst, sljit_sw dstw,2531sljit_s32 src, sljit_sw srcw)2532{2533sljit_s32 flags = 0;25342535CHECK_ERROR();2536CHECK(check_sljit_emit_op1(compiler, op, dst, dstw, src, srcw));2537ADJUST_LOCAL_OFFSET(dst, dstw);2538ADJUST_LOCAL_OFFSET(src, srcw);25392540#if (defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64)2541if (op & SLJIT_32)2542flags = INT_DATA | SIGNED_DATA;2543#endif25442545switch (GET_OPCODE(op)) {2546case SLJIT_MOV:2547#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)2548case SLJIT_MOV_U32:2549case SLJIT_MOV_S32:2550case SLJIT_MOV32:2551#endif2552case SLJIT_MOV_P:2553return emit_op(compiler, SLJIT_MOV, WORD_DATA | MOVE_OP, dst, dstw, TMP_REG1, 0, src, srcw);25542555#if (defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64)2556case SLJIT_MOV_U32:2557return emit_op(compiler, SLJIT_MOV_U32, INT_DATA | MOVE_OP, dst, dstw, TMP_REG1, 0, src, (src == SLJIT_IMM) ? (sljit_u32)srcw : srcw);25582559case SLJIT_MOV_S32:2560case SLJIT_MOV32:2561return emit_op(compiler, SLJIT_MOV_S32, INT_DATA | SIGNED_DATA | MOVE_OP, dst, dstw, TMP_REG1, 0, src, (src == SLJIT_IMM) ? (sljit_s32)srcw : srcw);2562#endif25632564case SLJIT_MOV_U8:2565return emit_op(compiler, op, BYTE_DATA | MOVE_OP, dst, dstw, TMP_REG1, 0, src, (src == SLJIT_IMM) ? (sljit_u8)srcw : srcw);25662567case SLJIT_MOV_S8:2568return emit_op(compiler, op, BYTE_DATA | SIGNED_DATA | MOVE_OP, dst, dstw, TMP_REG1, 0, src, (src == SLJIT_IMM) ? (sljit_s8)srcw : srcw);25692570case SLJIT_MOV_U16:2571return emit_op(compiler, op, HALF_DATA | MOVE_OP, dst, dstw, TMP_REG1, 0, src, (src == SLJIT_IMM) ? (sljit_u16)srcw : srcw);25722573case SLJIT_MOV_S16:2574return emit_op(compiler, op, HALF_DATA | SIGNED_DATA | MOVE_OP, dst, dstw, TMP_REG1, 0, src, (src == SLJIT_IMM) ? (sljit_s16)srcw : srcw);25752576case SLJIT_CLZ:2577case SLJIT_CTZ:2578case SLJIT_REV:2579return emit_op(compiler, op, flags, dst, dstw, TMP_REG1, 0, src, srcw);25802581case SLJIT_REV_U16:2582case SLJIT_REV_S16:2583return emit_op(compiler, op, HALF_DATA, dst, dstw, TMP_REG1, 0, src, srcw);25842585case SLJIT_REV_U32:2586case SLJIT_REV_S32:2587return emit_op(compiler, op | SLJIT_32, INT_DATA, dst, dstw, TMP_REG1, 0, src, srcw);2588}25892590SLJIT_UNREACHABLE();2591return SLJIT_SUCCESS;2592}25932594SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op2(struct sljit_compiler *compiler, sljit_s32 op,2595sljit_s32 dst, sljit_sw dstw,2596sljit_s32 src1, sljit_sw src1w,2597sljit_s32 src2, sljit_sw src2w)2598{2599sljit_s32 flags = 0;26002601CHECK_ERROR();2602CHECK(check_sljit_emit_op2(compiler, op, 0, dst, dstw, src1, src1w, src2, src2w));2603ADJUST_LOCAL_OFFSET(dst, dstw);2604ADJUST_LOCAL_OFFSET(src1, src1w);2605ADJUST_LOCAL_OFFSET(src2, src2w);26062607#if (defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64)2608if (op & SLJIT_32) {2609flags |= INT_DATA | SIGNED_DATA;2610if (src1 == SLJIT_IMM)2611src1w = (sljit_s32)src1w;2612if (src2 == SLJIT_IMM)2613src2w = (sljit_s32)src2w;2614}2615#endif26162617switch (GET_OPCODE(op)) {2618case SLJIT_ADD:2619case SLJIT_ADDC:2620compiler->status_flags_state = SLJIT_CURRENT_FLAGS_ADD;2621return emit_op(compiler, op, flags | CUMULATIVE_OP | IMM_OP, dst, dstw, src1, src1w, src2, src2w);26222623case SLJIT_SUB:2624case SLJIT_SUBC:2625compiler->status_flags_state = SLJIT_CURRENT_FLAGS_SUB;2626return emit_op(compiler, op, flags | IMM_OP, dst, dstw, src1, src1w, src2, src2w);26272628case SLJIT_MUL:2629compiler->status_flags_state = 0;2630return emit_op(compiler, op, flags | CUMULATIVE_OP, dst, dstw, src1, src1w, src2, src2w);26312632case SLJIT_XOR:2633if ((src1 == SLJIT_IMM && src1w == -1) || (src2 == SLJIT_IMM && src2w == -1)) {2634return emit_op(compiler, op, flags | CUMULATIVE_OP | IMM_OP, dst, dstw, src1, src1w, src2, src2w);2635}2636/* fallthrough */2637case SLJIT_AND:2638case SLJIT_OR:2639return emit_op(compiler, op, flags | CUMULATIVE_OP | LOGICAL_OP | IMM_OP, dst, dstw, src1, src1w, src2, src2w);26402641case SLJIT_SHL:2642case SLJIT_MSHL:2643case SLJIT_LSHR:2644case SLJIT_MLSHR:2645case SLJIT_ASHR:2646case SLJIT_MASHR:2647case SLJIT_ROTL:2648case SLJIT_ROTR:2649#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)2650if (src2 == SLJIT_IMM)2651src2w &= 0x1f;2652#else2653if (src2 == SLJIT_IMM) {2654if (op & SLJIT_32)2655src2w &= 0x1f;2656else2657src2w &= 0x3f;2658}2659#endif2660return emit_op(compiler, op, flags | IMM_OP, dst, dstw, src1, src1w, src2, src2w);2661}26622663SLJIT_UNREACHABLE();2664return SLJIT_SUCCESS;2665}26662667SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op2u(struct sljit_compiler *compiler, sljit_s32 op,2668sljit_s32 src1, sljit_sw src1w,2669sljit_s32 src2, sljit_sw src2w)2670{2671CHECK_ERROR();2672CHECK(check_sljit_emit_op2(compiler, op, 1, 0, 0, src1, src1w, src2, src2w));26732674SLJIT_SKIP_CHECKS(compiler);2675return sljit_emit_op2(compiler, op, 0, 0, src1, src1w, src2, src2w);2676}26772678#if (defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64)2679#define SELECT_OP3(op, src2w, D, D32, W) (((op & SLJIT_32) ? (W) : ((src2w) < 32) ? (D) : (D32)) | (((sljit_ins)src2w & 0x1f) << 6))2680#else /* !SLJIT_CONFIG_MIPS_64 */2681#define SELECT_OP3(op, src2w, D, D32, W) ((W) | ((sljit_ins)(src2w) << 6))2682#endif /* SLJIT_CONFIG_MIPS_64 */26832684SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op2r(struct sljit_compiler *compiler, sljit_s32 op,2685sljit_s32 dst_reg,2686sljit_s32 src1, sljit_sw src1w,2687sljit_s32 src2, sljit_sw src2w)2688{2689CHECK_ERROR();2690CHECK(check_sljit_emit_op2r(compiler, op, dst_reg, src1, src1w, src2, src2w));26912692switch (GET_OPCODE(op)) {2693case SLJIT_MULADD:2694SLJIT_SKIP_CHECKS(compiler);2695FAIL_IF(sljit_emit_op2(compiler, SLJIT_MUL | (op & SLJIT_32), TMP_REG2, 0, src1, src1w, src2, src2w));2696return push_inst(compiler, SELECT_OP(DADDU, ADDU) | S(dst_reg) | T(TMP_REG2) | D(dst_reg), DR(dst_reg));2697}26982699return SLJIT_SUCCESS;2700}27012702SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_shift_into(struct sljit_compiler *compiler, sljit_s32 op,2703sljit_s32 dst_reg,2704sljit_s32 src1_reg,2705sljit_s32 src2_reg,2706sljit_s32 src3, sljit_sw src3w)2707{2708sljit_s32 is_left;2709sljit_ins ins1, ins2, ins3;2710#if (defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64)2711sljit_s32 inp_flags = ((op & SLJIT_32) ? INT_DATA : WORD_DATA) | LOAD_DATA;2712sljit_sw bit_length = (op & SLJIT_32) ? 32 : 64;2713#else /* !SLJIT_CONFIG_MIPS_64 */2714sljit_s32 inp_flags = WORD_DATA | LOAD_DATA;2715sljit_sw bit_length = 32;2716#endif /* SLJIT_CONFIG_MIPS_64 */27172718CHECK_ERROR();2719CHECK(check_sljit_emit_shift_into(compiler, op, dst_reg, src1_reg, src2_reg, src3, src3w));27202721is_left = (GET_OPCODE(op) == SLJIT_SHL || GET_OPCODE(op) == SLJIT_MSHL);27222723if (src1_reg == src2_reg) {2724SLJIT_SKIP_CHECKS(compiler);2725return sljit_emit_op2(compiler, (is_left ? SLJIT_ROTL : SLJIT_ROTR) | (op & SLJIT_32), dst_reg, 0, src1_reg, 0, src3, src3w);2726}27272728ADJUST_LOCAL_OFFSET(src3, src3w);27292730if (src3 == SLJIT_IMM) {2731src3w &= bit_length - 1;27322733if (src3w == 0)2734return SLJIT_SUCCESS;27352736if (is_left) {2737ins1 = SELECT_OP3(op, src3w, DSLL, DSLL32, SLL);2738src3w = bit_length - src3w;2739ins2 = SELECT_OP3(op, src3w, DSRL, DSRL32, SRL);2740} else {2741ins1 = SELECT_OP3(op, src3w, DSRL, DSRL32, SRL);2742src3w = bit_length - src3w;2743ins2 = SELECT_OP3(op, src3w, DSLL, DSLL32, SLL);2744}27452746FAIL_IF(push_inst(compiler, ins1 | T(src1_reg) | D(dst_reg), DR(dst_reg)));2747FAIL_IF(push_inst(compiler, ins2 | T(src2_reg) | D(TMP_REG1), DR(TMP_REG1)));2748return push_inst(compiler, OR | S(dst_reg) | T(TMP_REG1) | D(dst_reg), DR(dst_reg));2749}27502751if (src3 & SLJIT_MEM) {2752FAIL_IF(emit_op_mem(compiler, inp_flags, DR(TMP_REG2), src3, src3w));2753src3 = TMP_REG2;2754} else if (dst_reg == src3) {2755FAIL_IF(push_inst(compiler, SELECT_OP(DADDU, ADDU) | S(src3) | TA(0) | D(TMP_REG2), DR(TMP_REG2)));2756src3 = TMP_REG2;2757}27582759if (is_left) {2760ins1 = SELECT_OP(DSRL, SRL);2761ins2 = SELECT_OP(DSLLV, SLLV);2762ins3 = SELECT_OP(DSRLV, SRLV);2763} else {2764ins1 = SELECT_OP(DSLL, SLL);2765ins2 = SELECT_OP(DSRLV, SRLV);2766ins3 = SELECT_OP(DSLLV, SLLV);2767}27682769FAIL_IF(push_inst(compiler, ins2 | S(src3) | T(src1_reg) | D(dst_reg), DR(dst_reg)));27702771if (!(op & SLJIT_SHIFT_INTO_NON_ZERO)) {2772FAIL_IF(push_inst(compiler, ins1 | T(src2_reg) | D(TMP_REG1) | (1 << 6), DR(TMP_REG1)));2773FAIL_IF(push_inst(compiler, XORI | S(src3) | T(TMP_REG2) | ((sljit_ins)bit_length - 1), DR(TMP_REG2)));2774src2_reg = TMP_REG1;2775} else2776FAIL_IF(push_inst(compiler, SELECT_OP(DSUBU, SUBU) | SA(0) | T(src3) | D(TMP_REG2), DR(TMP_REG2)));27772778FAIL_IF(push_inst(compiler, ins3 | S(TMP_REG2) | T(src2_reg) | D(TMP_REG1), DR(TMP_REG1)));2779return push_inst(compiler, OR | S(dst_reg) | T(TMP_REG1) | D(dst_reg), DR(dst_reg));2780}27812782#undef SELECT_OP327832784SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_src(struct sljit_compiler *compiler, sljit_s32 op,2785sljit_s32 src, sljit_sw srcw)2786{2787CHECK_ERROR();2788CHECK(check_sljit_emit_op_src(compiler, op, src, srcw));2789ADJUST_LOCAL_OFFSET(src, srcw);27902791switch (op) {2792case SLJIT_FAST_RETURN:2793if (FAST_IS_REG(src))2794FAIL_IF(push_inst(compiler, ADDU_W | S(src) | TA(0) | DA(RETURN_ADDR_REG), RETURN_ADDR_REG));2795else2796FAIL_IF(emit_op_mem(compiler, WORD_DATA | LOAD_DATA, RETURN_ADDR_REG, src, srcw));27972798FAIL_IF(push_inst(compiler, JR | SA(RETURN_ADDR_REG), UNMOVABLE_INS));2799return push_inst(compiler, NOP, UNMOVABLE_INS);2800case SLJIT_SKIP_FRAMES_BEFORE_FAST_RETURN:2801return SLJIT_SUCCESS;2802case SLJIT_PREFETCH_L1:2803case SLJIT_PREFETCH_L2:2804case SLJIT_PREFETCH_L3:2805case SLJIT_PREFETCH_ONCE:2806#if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 1)2807return emit_prefetch(compiler, src, srcw);2808#else /* SLJIT_MIPS_REV < 1 */2809return SLJIT_SUCCESS;2810#endif /* SLJIT_MIPS_REV >= 1 */2811}28122813return SLJIT_SUCCESS;2814}28152816SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_dst(struct sljit_compiler *compiler, sljit_s32 op,2817sljit_s32 dst, sljit_sw dstw)2818{2819sljit_s32 dst_ar = RETURN_ADDR_REG;28202821CHECK_ERROR();2822CHECK(check_sljit_emit_op_dst(compiler, op, dst, dstw));2823ADJUST_LOCAL_OFFSET(dst, dstw);28242825switch (op) {2826case SLJIT_FAST_ENTER:2827if (FAST_IS_REG(dst))2828return push_inst(compiler, ADDU_W | SA(RETURN_ADDR_REG) | TA(0) | D(dst), UNMOVABLE_INS);2829break;2830case SLJIT_GET_RETURN_ADDRESS:2831dst_ar = DR(FAST_IS_REG(dst) ? dst : TMP_REG2);2832FAIL_IF(emit_op_mem(compiler, WORD_DATA | LOAD_DATA, dst_ar, SLJIT_MEM1(SLJIT_SP), compiler->local_size - SSIZE_OF(sw)));2833break;2834}28352836if (dst & SLJIT_MEM) {2837FAIL_IF(emit_op_mem(compiler, WORD_DATA, dst_ar, dst, dstw));28382839if (op == SLJIT_FAST_ENTER)2840compiler->delay_slot = UNMOVABLE_INS;2841}28422843return SLJIT_SUCCESS;2844}28452846SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_get_register_index(sljit_s32 type, sljit_s32 reg)2847{2848CHECK_REG_INDEX(check_sljit_get_register_index(type, reg));28492850if (type == SLJIT_GP_REGISTER)2851return reg_map[reg];28522853if (type != SLJIT_FLOAT_REGISTER)2854return -1;28552856return FR(reg);2857}28582859SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_custom(struct sljit_compiler *compiler,2860void *instruction, sljit_u32 size)2861{2862SLJIT_UNUSED_ARG(size);28632864CHECK_ERROR();2865CHECK(check_sljit_emit_op_custom(compiler, instruction, size));28662867return push_inst(compiler, *(sljit_ins*)instruction, UNMOVABLE_INS);2868}28692870/* --------------------------------------------------------------------- */2871/* Floating point operators */2872/* --------------------------------------------------------------------- */28732874#define FLOAT_DATA(op) (DOUBLE_DATA | ((op & SLJIT_32) >> 7))2875#define FMT(op) (FMT_S | (~(sljit_ins)op & SLJIT_32) << (21 - (5 + 3)))28762877static SLJIT_INLINE sljit_s32 sljit_emit_fop1_conv_sw_from_f64(struct sljit_compiler *compiler, sljit_s32 op,2878sljit_s32 dst, sljit_sw dstw,2879sljit_s32 src, sljit_sw srcw)2880{2881#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)2882sljit_u32 flags = 0;2883#else2884sljit_u32 flags = ((sljit_u32)(GET_OPCODE(op) == SLJIT_CONV_SW_FROM_F64)) << 21;2885#endif28862887if (src & SLJIT_MEM) {2888FAIL_IF(emit_op_mem2(compiler, FLOAT_DATA(op) | LOAD_DATA, FR(TMP_FREG1), src, srcw, dst, dstw));2889src = TMP_FREG1;2890}28912892FAIL_IF(push_inst(compiler, (TRUNC_W_S ^ (flags >> 19)) | FMT(op) | FS(src) | FD(TMP_FREG1), MOVABLE_INS));28932894if (FAST_IS_REG(dst)) {2895FAIL_IF(push_inst(compiler, MFC1 | flags | T(dst) | FS(TMP_FREG1), MOVABLE_INS));2896#if !defined(SLJIT_MIPS_REV) || (SLJIT_CONFIG_MIPS_32 && SLJIT_MIPS_REV <= 1)2897FAIL_IF(push_inst(compiler, NOP, UNMOVABLE_INS));2898#endif /* MIPS III */2899return SLJIT_SUCCESS;2900}29012902return emit_op_mem2(compiler, flags ? DOUBLE_DATA : SINGLE_DATA, FR(TMP_FREG1), dst, dstw, 0, 0);2903}29042905static SLJIT_INLINE sljit_s32 sljit_emit_fop1_conv_f64_from_sw(struct sljit_compiler *compiler, sljit_s32 op,2906sljit_s32 dst, sljit_sw dstw,2907sljit_s32 src, sljit_sw srcw)2908{2909#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)2910sljit_u32 flags = 0;2911#else2912sljit_u32 flags = ((sljit_u32)(GET_OPCODE(op) == SLJIT_CONV_F64_FROM_SW)) << 21;2913#endif2914sljit_s32 dst_r = FAST_IS_REG(dst) ? dst : TMP_FREG1;29152916if (src & SLJIT_MEM)2917FAIL_IF(emit_op_mem2(compiler, (flags ? DOUBLE_DATA : SINGLE_DATA) | LOAD_DATA, FR(TMP_FREG1), src, srcw, dst, dstw));2918else {2919if (src == SLJIT_IMM) {2920#if (defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64)2921if (GET_OPCODE(op) == SLJIT_CONV_F64_FROM_S32)2922srcw = (sljit_s32)srcw;2923#endif2924FAIL_IF(load_immediate(compiler, DR(TMP_REG1), srcw));2925src = TMP_REG1;2926}29272928FAIL_IF(push_inst(compiler, MTC1 | flags | T(src) | FS(TMP_FREG1), MOVABLE_INS));2929#if !defined(SLJIT_MIPS_REV) || (SLJIT_CONFIG_MIPS_32 && SLJIT_MIPS_REV <= 1)2930FAIL_IF(push_inst(compiler, NOP, UNMOVABLE_INS));2931#endif /* MIPS III */2932}29332934FAIL_IF(push_inst(compiler, CVT_S_S | flags | (4 << 21) | ((~(sljit_ins)op & SLJIT_32) >> 8) | FS(TMP_FREG1) | FD(dst_r), MOVABLE_INS));29352936if (dst & SLJIT_MEM)2937return emit_op_mem2(compiler, FLOAT_DATA(op), FR(TMP_FREG1), dst, dstw, 0, 0);2938return SLJIT_SUCCESS;2939}29402941static SLJIT_INLINE sljit_s32 sljit_emit_fop1_conv_f64_from_uw(struct sljit_compiler *compiler, sljit_s32 op,2942sljit_s32 dst, sljit_sw dstw,2943sljit_s32 src, sljit_sw srcw)2944{2945#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)2946sljit_u32 flags = 0;2947#else2948sljit_u32 flags = 1 << 21;2949#endif2950sljit_s32 dst_r = FAST_IS_REG(dst) ? dst : TMP_FREG1;29512952if (src & SLJIT_MEM) {2953FAIL_IF(emit_op_mem2(compiler, (GET_OPCODE(op) == SLJIT_CONV_F64_FROM_UW ? WORD_DATA : INT_DATA) | LOAD_DATA, DR(TMP_REG1), src, srcw, dst, dstw));2954src = TMP_REG1;2955} else if (src == SLJIT_IMM) {2956#if (defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64)2957if (GET_OPCODE(op) == SLJIT_CONV_F64_FROM_U32)2958srcw = (sljit_u32)srcw;2959#endif2960FAIL_IF(load_immediate(compiler, DR(TMP_REG1), srcw));2961src = TMP_REG1;2962}29632964#if (defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64)2965if (GET_OPCODE(op) == SLJIT_CONV_F64_FROM_U32) {2966if (src != TMP_REG1) {2967FAIL_IF(push_inst(compiler, DSLL32 | T(src) | D(TMP_REG1) | SH_IMM(0), DR(TMP_REG1)));2968FAIL_IF(push_inst(compiler, DSRL32 | T(TMP_REG1) | D(TMP_REG1) | SH_IMM(0), DR(TMP_REG1)));2969}29702971FAIL_IF(push_inst(compiler, MTC1 | flags | T(TMP_REG1) | FS(TMP_FREG1), MOVABLE_INS));2972#if !defined(SLJIT_MIPS_REV)2973FAIL_IF(push_inst(compiler, NOP, UNMOVABLE_INS));2974#endif /* MIPS III */29752976FAIL_IF(push_inst(compiler, CVT_S_S | flags | (4 << 21) | ((~(sljit_ins)op & SLJIT_32) >> 8) | FS(TMP_FREG1) | FD(dst_r), MOVABLE_INS));29772978if (dst & SLJIT_MEM)2979return emit_op_mem2(compiler, FLOAT_DATA(op), FR(TMP_FREG1), dst, dstw, 0, 0);2980return SLJIT_SUCCESS;2981}2982#else /* !SLJIT_CONFIG_MIPS_64 */2983if (!(op & SLJIT_32)) {2984FAIL_IF(push_inst(compiler, SLL | T(src) | D(TMP_REG2) | SH_IMM(1), DR(TMP_REG2)));2985FAIL_IF(push_inst(compiler, SRL | T(TMP_REG2) | D(TMP_REG2) | SH_IMM(1), DR(TMP_REG2)));29862987FAIL_IF(push_inst(compiler, MTC1 | flags | T(TMP_REG2) | FS(TMP_FREG1), MOVABLE_INS));2988#if !defined(SLJIT_MIPS_REV) || SLJIT_MIPS_REV <= 12989FAIL_IF(push_inst(compiler, NOP, UNMOVABLE_INS));2990#endif /* MIPS III */29912992FAIL_IF(push_inst(compiler, CVT_S_S | flags | (4 << 21) | 1 | FS(TMP_FREG1) | FD(dst_r), MOVABLE_INS));29932994#if (!defined SLJIT_MIPS_REV || SLJIT_MIPS_REV <= 1)2995FAIL_IF(push_inst(compiler, BGEZ | S(src) | 5, UNMOVABLE_INS));2996#else /* SLJIT_MIPS_REV >= 1 */2997FAIL_IF(push_inst(compiler, BGEZ | S(src) | 4, UNMOVABLE_INS));2998#endif /* SLJIT_MIPS_REV < 1 */29993000FAIL_IF(push_inst(compiler, LUI | T(TMP_REG2) | IMM(0x41e0), UNMOVABLE_INS));3001FAIL_IF(push_inst(compiler, MTC1 | TA(0) | FS(TMP_FREG2), UNMOVABLE_INS));3002switch (cpu_feature_list & CPU_FEATURE_FR) {3003#if defined(SLJIT_MIPS_REV) && SLJIT_MIPS_REV >= 23004case CPU_FEATURE_FR:3005FAIL_IF(push_inst(compiler, MTHC1 | T(TMP_REG2) | FS(TMP_FREG2), UNMOVABLE_INS));3006break;3007#endif /* SLJIT_MIPS_REV >= 2 */3008default:3009FAIL_IF(push_inst(compiler, MTC1 | T(TMP_REG2) | FS(TMP_FREG2) | (1 << 11), UNMOVABLE_INS));3010#if !defined(SLJIT_MIPS_REV) || SLJIT_MIPS_REV <= 13011FAIL_IF(push_inst(compiler, NOP, UNMOVABLE_INS));3012#endif /* MIPS III */3013break;3014}3015FAIL_IF(push_inst(compiler, ADD_S | FMT(op) | FT(TMP_FREG2) | FS(dst_r) | FD(dst_r), UNMOVABLE_INS));30163017if (dst & SLJIT_MEM)3018return emit_op_mem2(compiler, FLOAT_DATA(op), FR(TMP_FREG1), dst, dstw, 0, 0);3019return SLJIT_SUCCESS;3020}3021#endif /* SLJIT_CONFIG_MIPS_64 */30223023#if (!defined SLJIT_MIPS_REV || SLJIT_MIPS_REV <= 1)3024FAIL_IF(push_inst(compiler, BLTZ | S(src) | 5, UNMOVABLE_INS));3025#else /* SLJIT_MIPS_REV >= 1 */3026FAIL_IF(push_inst(compiler, BLTZ | S(src) | 4, UNMOVABLE_INS));3027#endif /* SLJIT_MIPS_REV < 1 */3028FAIL_IF(push_inst(compiler, ANDI | S(src) | T(TMP_REG2) | IMM(1), DR(TMP_REG2)));30293030FAIL_IF(push_inst(compiler, MTC1 | flags | T(src) | FS(TMP_FREG1), MOVABLE_INS));3031#if !defined(SLJIT_MIPS_REV)3032FAIL_IF(push_inst(compiler, NOP, UNMOVABLE_INS));3033#endif /* !SLJIT_MIPS_REV */30343035FAIL_IF(push_inst(compiler, CVT_S_S | flags | (4 << 21) | ((~(sljit_ins)op & SLJIT_32) >> 8) | FS(TMP_FREG1) | FD(dst_r), MOVABLE_INS));30363037#if (!defined SLJIT_MIPS_REV || SLJIT_MIPS_REV <= 1)3038FAIL_IF(push_inst(compiler, BEQ | 6, UNMOVABLE_INS));3039#else /* SLJIT_MIPS_REV >= 1 */3040FAIL_IF(push_inst(compiler, BEQ | 5, UNMOVABLE_INS));3041#endif /* SLJIT_MIPS_REV < 1 */30423043#if (defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64)3044FAIL_IF(push_inst(compiler, DSRL | T(src) | D(TMP_REG1) | SH_IMM(1), DR(TMP_REG1)));3045#else /* !SLJIT_CONFIG_MIPS_64 */3046FAIL_IF(push_inst(compiler, SRL | T(src) | D(TMP_REG1) | SH_IMM(1), DR(TMP_REG1)));3047#endif /* SLJIT_CONFIG_MIPS_64 */30483049FAIL_IF(push_inst(compiler, OR | S(TMP_REG1) | T(TMP_REG2) | D(TMP_REG1), DR(TMP_REG1)));30503051FAIL_IF(push_inst(compiler, MTC1 | flags | T(TMP_REG1) | FS(TMP_FREG1), MOVABLE_INS));3052#if !defined(SLJIT_MIPS_REV)3053FAIL_IF(push_inst(compiler, NOP, UNMOVABLE_INS));3054#endif /* !SLJIT_MIPS_REV */30553056FAIL_IF(push_inst(compiler, CVT_S_S | flags | (4 << 21) | ((~(sljit_ins)op & SLJIT_32) >> 8) | FS(TMP_FREG1) | FD(dst_r), MOVABLE_INS));3057FAIL_IF(push_inst(compiler, ADD_S | FMT(op) | FT(dst_r) | FS(dst_r) | FD(dst_r), UNMOVABLE_INS));30583059if (dst & SLJIT_MEM)3060return emit_op_mem2(compiler, FLOAT_DATA(op), FR(TMP_FREG1), dst, dstw, 0, 0);3061return SLJIT_SUCCESS;3062}30633064static SLJIT_INLINE sljit_s32 sljit_emit_fop1_cmp(struct sljit_compiler *compiler, sljit_s32 op,3065sljit_s32 src1, sljit_sw src1w,3066sljit_s32 src2, sljit_sw src2w)3067{3068sljit_ins inst;30693070if (src1 & SLJIT_MEM) {3071FAIL_IF(emit_op_mem2(compiler, FLOAT_DATA(op) | LOAD_DATA, FR(TMP_FREG1), src1, src1w, src2, src2w));3072src1 = TMP_FREG1;3073}30743075if (src2 & SLJIT_MEM) {3076FAIL_IF(emit_op_mem2(compiler, FLOAT_DATA(op) | LOAD_DATA, FR(TMP_FREG2), src2, src2w, 0, 0));3077src2 = TMP_FREG2;3078}30793080switch (GET_FLAG_TYPE(op)) {3081case SLJIT_F_EQUAL:3082case SLJIT_ORDERED_EQUAL:3083inst = C_EQ_S;3084break;3085case SLJIT_F_NOT_EQUAL:3086case SLJIT_UNORDERED_OR_EQUAL:3087inst = C_UEQ_S;3088break;3089case SLJIT_F_LESS:3090case SLJIT_ORDERED_LESS:3091inst = C_OLT_S;3092break;3093case SLJIT_F_GREATER_EQUAL:3094case SLJIT_UNORDERED_OR_LESS:3095inst = C_ULT_S;3096break;3097case SLJIT_F_GREATER:3098case SLJIT_ORDERED_GREATER:3099inst = C_ULE_S;3100break;3101case SLJIT_F_LESS_EQUAL:3102case SLJIT_UNORDERED_OR_GREATER:3103inst = C_OLE_S;3104break;3105default:3106SLJIT_ASSERT(GET_FLAG_TYPE(op) == SLJIT_UNORDERED);3107inst = C_UN_S;3108break;3109}3110return push_inst(compiler, inst | FMT(op) | FT(src2) | FS(src1) | C_FD, UNMOVABLE_INS);3111}31123113SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fop1(struct sljit_compiler *compiler, sljit_s32 op,3114sljit_s32 dst, sljit_sw dstw,3115sljit_s32 src, sljit_sw srcw)3116{3117sljit_s32 dst_r;31183119CHECK_ERROR();3120compiler->cache_arg = 0;3121compiler->cache_argw = 0;31223123SLJIT_COMPILE_ASSERT((SLJIT_32 == 0x100) && !(DOUBLE_DATA & 0x2), float_transfer_bit_error);3124SELECT_FOP1_OPERATION_WITH_CHECKS(compiler, op, dst, dstw, src, srcw);31253126if (GET_OPCODE(op) == SLJIT_CONV_F64_FROM_F32)3127op ^= SLJIT_32;31283129dst_r = FAST_IS_REG(dst) ? dst : TMP_FREG1;31303131if (src & SLJIT_MEM) {3132FAIL_IF(emit_op_mem2(compiler, FLOAT_DATA(op) | LOAD_DATA, FR(dst_r), src, srcw, dst, dstw));3133src = dst_r;3134}31353136switch (GET_OPCODE(op)) {3137case SLJIT_MOV_F64:3138if (src != dst_r) {3139if (!(dst & SLJIT_MEM))3140FAIL_IF(push_inst(compiler, MOV_fmt(FMT(op)) | FS(src) | FD(dst_r), MOVABLE_INS));3141else3142dst_r = src;3143}3144break;3145case SLJIT_NEG_F64:3146FAIL_IF(push_inst(compiler, NEG_S | FMT(op) | FS(src) | FD(dst_r), MOVABLE_INS));3147break;3148case SLJIT_ABS_F64:3149FAIL_IF(push_inst(compiler, ABS_S | FMT(op) | FS(src) | FD(dst_r), MOVABLE_INS));3150break;3151case SLJIT_CONV_F64_FROM_F32:3152/* The SLJIT_32 bit is inverted because sljit_f32 needs to be loaded from the memory. */3153FAIL_IF(push_inst(compiler, CVT_S_S | (sljit_ins)((op & SLJIT_32) ? 1 : (1 << 21)) | FS(src) | FD(dst_r), MOVABLE_INS));3154op ^= SLJIT_32;3155break;3156}31573158if (dst & SLJIT_MEM)3159return emit_op_mem2(compiler, FLOAT_DATA(op), FR(dst_r), dst, dstw, 0, 0);3160return SLJIT_SUCCESS;3161}31623163SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fop2(struct sljit_compiler *compiler, sljit_s32 op,3164sljit_s32 dst, sljit_sw dstw,3165sljit_s32 src1, sljit_sw src1w,3166sljit_s32 src2, sljit_sw src2w)3167{3168sljit_s32 dst_r, flags = 0;31693170CHECK_ERROR();3171CHECK(check_sljit_emit_fop2(compiler, op, dst, dstw, src1, src1w, src2, src2w));3172ADJUST_LOCAL_OFFSET(dst, dstw);3173ADJUST_LOCAL_OFFSET(src1, src1w);3174ADJUST_LOCAL_OFFSET(src2, src2w);31753176compiler->cache_arg = 0;3177compiler->cache_argw = 0;31783179dst_r = FAST_IS_REG(dst) ? dst : TMP_FREG2;31803181if (src1 & SLJIT_MEM) {3182if (getput_arg_fast(compiler, FLOAT_DATA(op) | LOAD_DATA, FR(TMP_FREG1), src1, src1w)) {3183FAIL_IF(compiler->error);3184src1 = TMP_FREG1;3185} else3186flags |= SLOW_SRC1;3187}31883189if (src2 & SLJIT_MEM) {3190if (getput_arg_fast(compiler, FLOAT_DATA(op) | LOAD_DATA, FR(TMP_FREG2), src2, src2w)) {3191FAIL_IF(compiler->error);3192src2 = TMP_FREG2;3193} else3194flags |= SLOW_SRC2;3195}31963197if ((flags & (SLOW_SRC1 | SLOW_SRC2)) == (SLOW_SRC1 | SLOW_SRC2)) {3198if ((dst & SLJIT_MEM) && !can_cache(src1, src1w, src2, src2w) && can_cache(src1, src1w, dst, dstw)) {3199FAIL_IF(getput_arg(compiler, FLOAT_DATA(op) | LOAD_DATA, FR(TMP_FREG2), src2, src2w, src1, src1w));3200FAIL_IF(getput_arg(compiler, FLOAT_DATA(op) | LOAD_DATA, FR(TMP_FREG1), src1, src1w, dst, dstw));3201} else {3202FAIL_IF(getput_arg(compiler, FLOAT_DATA(op) | LOAD_DATA, FR(TMP_FREG1), src1, src1w, src2, src2w));3203FAIL_IF(getput_arg(compiler, FLOAT_DATA(op) | LOAD_DATA, FR(TMP_FREG2), src2, src2w, dst, dstw));3204}3205}3206else if (flags & SLOW_SRC1)3207FAIL_IF(getput_arg(compiler, FLOAT_DATA(op) | LOAD_DATA, FR(TMP_FREG1), src1, src1w, dst, dstw));3208else if (flags & SLOW_SRC2)3209FAIL_IF(getput_arg(compiler, FLOAT_DATA(op) | LOAD_DATA, FR(TMP_FREG2), src2, src2w, dst, dstw));32103211if (flags & SLOW_SRC1)3212src1 = TMP_FREG1;3213if (flags & SLOW_SRC2)3214src2 = TMP_FREG2;32153216switch (GET_OPCODE(op)) {3217case SLJIT_ADD_F64:3218FAIL_IF(push_inst(compiler, ADD_S | FMT(op) | FT(src2) | FS(src1) | FD(dst_r), MOVABLE_INS));3219break;3220case SLJIT_SUB_F64:3221FAIL_IF(push_inst(compiler, SUB_S | FMT(op) | FT(src2) | FS(src1) | FD(dst_r), MOVABLE_INS));3222break;3223case SLJIT_MUL_F64:3224FAIL_IF(push_inst(compiler, MUL_S | FMT(op) | FT(src2) | FS(src1) | FD(dst_r), MOVABLE_INS));3225break;3226case SLJIT_DIV_F64:3227FAIL_IF(push_inst(compiler, DIV_S | FMT(op) | FT(src2) | FS(src1) | FD(dst_r), MOVABLE_INS));3228break;3229case SLJIT_COPYSIGN_F64:3230return emit_copysign(compiler, op, src1, src2, dst_r);3231}32323233if (dst_r == TMP_FREG2)3234FAIL_IF(emit_op_mem2(compiler, FLOAT_DATA(op), FR(TMP_FREG2), dst, dstw, 0, 0));32353236return SLJIT_SUCCESS;3237}32383239SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fset32(struct sljit_compiler *compiler,3240sljit_s32 freg, sljit_f32 value)3241{3242union {3243sljit_s32 imm;3244sljit_f32 value;3245} u;32463247CHECK_ERROR();3248CHECK(check_sljit_emit_fset32(compiler, freg, value));32493250u.value = value;32513252if (u.imm == 0)3253return push_inst(compiler, MTC1 | TA(0) | FS(freg), MOVABLE_INS);32543255FAIL_IF(load_immediate(compiler, DR(TMP_REG1), u.imm));3256return push_inst(compiler, MTC1 | T(TMP_REG1) | FS(freg), MOVABLE_INS);3257}32583259/* --------------------------------------------------------------------- */3260/* Conditional instructions */3261/* --------------------------------------------------------------------- */32623263SLJIT_API_FUNC_ATTRIBUTE struct sljit_label* sljit_emit_label(struct sljit_compiler *compiler)3264{3265struct sljit_label *label;32663267CHECK_ERROR_PTR();3268CHECK_PTR(check_sljit_emit_label(compiler));32693270if (compiler->last_label && compiler->last_label->size == compiler->size)3271return compiler->last_label;32723273label = (struct sljit_label*)ensure_abuf(compiler, sizeof(struct sljit_label));3274PTR_FAIL_IF(!label);3275set_label(label, compiler);3276compiler->delay_slot = UNMOVABLE_INS;3277return label;3278}32793280#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)3281#define BRANCH_LENGTH 43282#else3283#define BRANCH_LENGTH 83284#endif32853286#define BR_Z(src) \3287inst = BEQ | SA(src) | TA(0) | BRANCH_LENGTH; \3288flags = IS_BIT26_COND; \3289delay_check = src;32903291#define BR_NZ(src) \3292inst = BNE | SA(src) | TA(0) | BRANCH_LENGTH; \3293flags = IS_BIT26_COND; \3294delay_check = src;32953296#if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 6)32973298#define BR_T() \3299inst = BC1NEZ; \3300flags = IS_BIT23_COND; \3301delay_check = FCSR_FCC;3302#define BR_F() \3303inst = BC1EQZ; \3304flags = IS_BIT23_COND; \3305delay_check = FCSR_FCC;33063307#else /* SLJIT_MIPS_REV < 6 */33083309#define BR_T() \3310inst = BC1T | BRANCH_LENGTH; \3311flags = IS_BIT16_COND; \3312delay_check = FCSR_FCC;3313#define BR_F() \3314inst = BC1F | BRANCH_LENGTH; \3315flags = IS_BIT16_COND; \3316delay_check = FCSR_FCC;33173318#endif /* SLJIT_MIPS_REV >= 6 */33193320SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_jump(struct sljit_compiler *compiler, sljit_s32 type)3321{3322struct sljit_jump *jump;3323sljit_ins inst;3324sljit_u32 flags = 0;3325sljit_s32 delay_check = UNMOVABLE_INS;33263327CHECK_ERROR_PTR();3328CHECK_PTR(check_sljit_emit_jump(compiler, type));33293330jump = (struct sljit_jump*)ensure_abuf(compiler, sizeof(struct sljit_jump));3331PTR_FAIL_IF(!jump);3332set_jump(jump, compiler, type & SLJIT_REWRITABLE_JUMP);3333type &= 0xff;33343335switch (type) {3336case SLJIT_EQUAL:3337BR_NZ(EQUAL_FLAG);3338break;3339case SLJIT_NOT_EQUAL:3340BR_Z(EQUAL_FLAG);3341break;3342case SLJIT_LESS:3343case SLJIT_GREATER:3344case SLJIT_SIG_LESS:3345case SLJIT_SIG_GREATER:3346case SLJIT_OVERFLOW:3347case SLJIT_CARRY:3348case SLJIT_ATOMIC_STORED:3349BR_Z(OTHER_FLAG);3350break;3351case SLJIT_GREATER_EQUAL:3352case SLJIT_LESS_EQUAL:3353case SLJIT_SIG_GREATER_EQUAL:3354case SLJIT_SIG_LESS_EQUAL:3355case SLJIT_NOT_OVERFLOW:3356case SLJIT_NOT_CARRY:3357case SLJIT_ATOMIC_NOT_STORED:3358BR_NZ(OTHER_FLAG);3359break;3360case SLJIT_F_NOT_EQUAL:3361case SLJIT_F_GREATER_EQUAL:3362case SLJIT_F_GREATER:3363case SLJIT_UNORDERED_OR_NOT_EQUAL:3364case SLJIT_ORDERED_NOT_EQUAL:3365case SLJIT_UNORDERED_OR_GREATER_EQUAL:3366case SLJIT_ORDERED_GREATER_EQUAL:3367case SLJIT_ORDERED_GREATER:3368case SLJIT_UNORDERED_OR_GREATER:3369case SLJIT_ORDERED:3370BR_T();3371break;3372case SLJIT_F_EQUAL:3373case SLJIT_F_LESS:3374case SLJIT_F_LESS_EQUAL:3375case SLJIT_ORDERED_EQUAL:3376case SLJIT_UNORDERED_OR_EQUAL:3377case SLJIT_ORDERED_LESS:3378case SLJIT_UNORDERED_OR_LESS:3379case SLJIT_UNORDERED_OR_LESS_EQUAL:3380case SLJIT_ORDERED_LESS_EQUAL:3381case SLJIT_UNORDERED:3382BR_F();3383break;3384default:3385/* Not conditional branch. */3386inst = 0;3387break;3388}33893390jump->flags |= flags;3391if (compiler->delay_slot == MOVABLE_INS || (compiler->delay_slot != UNMOVABLE_INS && compiler->delay_slot != delay_check))3392jump->flags |= IS_MOVABLE;33933394if (inst)3395PTR_FAIL_IF(push_inst(compiler, inst, UNMOVABLE_INS));33963397if (type <= SLJIT_JUMP)3398PTR_FAIL_IF(push_inst(compiler, JR | S(PIC_ADDR_REG), UNMOVABLE_INS));3399else {3400jump->flags |= IS_JAL;3401PTR_FAIL_IF(push_inst(compiler, JALR | S(PIC_ADDR_REG) | DA(RETURN_ADDR_REG), UNMOVABLE_INS));3402}34033404jump->addr = compiler->size;3405PTR_FAIL_IF(push_inst(compiler, NOP, UNMOVABLE_INS));34063407/* Maximum number of instructions required for generating a constant. */3408#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)3409compiler->size += 2;3410#else3411compiler->size += 6;3412#endif3413return jump;3414}34153416#define RESOLVE_IMM1() \3417if (src1 == SLJIT_IMM) { \3418if (src1w) { \3419PTR_FAIL_IF(load_immediate(compiler, DR(TMP_REG1), src1w)); \3420src1 = TMP_REG1; \3421} \3422else \3423src1 = 0; \3424}34253426#define RESOLVE_IMM2() \3427if (src2 == SLJIT_IMM) { \3428if (src2w) { \3429PTR_FAIL_IF(load_immediate(compiler, DR(src2_tmp_reg), src2w)); \3430src2 = src2_tmp_reg; \3431} \3432else \3433src2 = 0; \3434}34353436SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_cmp(struct sljit_compiler *compiler, sljit_s32 type,3437sljit_s32 src1, sljit_sw src1w,3438sljit_s32 src2, sljit_sw src2w)3439{3440struct sljit_jump *jump;3441sljit_s32 flags;3442sljit_ins inst;3443sljit_s32 src2_tmp_reg = FAST_IS_REG(src1) ? TMP_REG1 : TMP_REG2;34443445CHECK_ERROR_PTR();3446CHECK_PTR(check_sljit_emit_cmp(compiler, type, src1, src1w, src2, src2w));3447ADJUST_LOCAL_OFFSET(src1, src1w);3448ADJUST_LOCAL_OFFSET(src2, src2w);34493450compiler->cache_arg = 0;3451compiler->cache_argw = 0;3452#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)3453flags = WORD_DATA | LOAD_DATA;3454#else /* !SLJIT_CONFIG_MIPS_32 */3455flags = ((type & SLJIT_32) ? INT_DATA : WORD_DATA) | LOAD_DATA;3456#endif /* SLJIT_CONFIG_MIPS_32 */34573458if (src1 & SLJIT_MEM) {3459PTR_FAIL_IF(emit_op_mem2(compiler, flags, DR(TMP_REG1), src1, src1w, src2, src2w));3460src1 = TMP_REG1;3461}34623463if (src2 & SLJIT_MEM) {3464PTR_FAIL_IF(emit_op_mem2(compiler, flags, DR(src2_tmp_reg), src2, src2w, 0, 0));3465src2 = src2_tmp_reg;3466}34673468jump = (struct sljit_jump*)ensure_abuf(compiler, sizeof(struct sljit_jump));3469PTR_FAIL_IF(!jump);3470set_jump(jump, compiler, type & SLJIT_REWRITABLE_JUMP);3471type &= 0xff;34723473if (type <= SLJIT_NOT_EQUAL) {3474RESOLVE_IMM1();3475RESOLVE_IMM2();3476jump->flags |= IS_BIT26_COND;3477if (compiler->delay_slot == MOVABLE_INS || (compiler->delay_slot != UNMOVABLE_INS && compiler->delay_slot != DR(src1) && compiler->delay_slot != DR(src2)))3478jump->flags |= IS_MOVABLE;3479PTR_FAIL_IF(push_inst(compiler, (type == SLJIT_EQUAL ? BNE : BEQ) | S(src1) | T(src2) | BRANCH_LENGTH, UNMOVABLE_INS));3480} else if (type >= SLJIT_SIG_LESS && ((src1 == SLJIT_IMM && src1w == 0) || (src2 == SLJIT_IMM && src2w == 0))) {3481inst = NOP;3482if (src1 == SLJIT_IMM && src1w == 0) {3483RESOLVE_IMM2();3484switch (type) {3485case SLJIT_SIG_LESS:3486inst = BLEZ;3487jump->flags |= IS_BIT26_COND;3488break;3489case SLJIT_SIG_GREATER_EQUAL:3490inst = BGTZ;3491jump->flags |= IS_BIT26_COND;3492break;3493case SLJIT_SIG_GREATER:3494inst = BGEZ;3495jump->flags |= IS_BIT16_COND;3496break;3497case SLJIT_SIG_LESS_EQUAL:3498inst = BLTZ;3499jump->flags |= IS_BIT16_COND;3500break;3501}3502src1 = src2;3503}3504else {3505RESOLVE_IMM1();3506switch (type) {3507case SLJIT_SIG_LESS:3508inst = BGEZ;3509jump->flags |= IS_BIT16_COND;3510break;3511case SLJIT_SIG_GREATER_EQUAL:3512inst = BLTZ;3513jump->flags |= IS_BIT16_COND;3514break;3515case SLJIT_SIG_GREATER:3516inst = BLEZ;3517jump->flags |= IS_BIT26_COND;3518break;3519case SLJIT_SIG_LESS_EQUAL:3520inst = BGTZ;3521jump->flags |= IS_BIT26_COND;3522break;3523}3524}3525PTR_FAIL_IF(push_inst(compiler, inst | S(src1) | BRANCH_LENGTH, UNMOVABLE_INS));3526}3527else {3528if (type == SLJIT_LESS || type == SLJIT_GREATER_EQUAL || type == SLJIT_SIG_LESS || type == SLJIT_SIG_GREATER_EQUAL) {3529RESOLVE_IMM1();3530if (src2 == SLJIT_IMM && src2w <= SIMM_MAX && src2w >= SIMM_MIN)3531PTR_FAIL_IF(push_inst(compiler, (type <= SLJIT_LESS_EQUAL ? SLTIU : SLTI) | S(src1) | T(TMP_REG1) | IMM(src2w), DR(TMP_REG1)));3532else {3533RESOLVE_IMM2();3534PTR_FAIL_IF(push_inst(compiler, (type <= SLJIT_LESS_EQUAL ? SLTU : SLT) | S(src1) | T(src2) | D(TMP_REG1), DR(TMP_REG1)));3535}3536type = (type == SLJIT_LESS || type == SLJIT_SIG_LESS) ? SLJIT_NOT_EQUAL : SLJIT_EQUAL;3537}3538else {3539RESOLVE_IMM2();3540if (src1 == SLJIT_IMM && src1w <= SIMM_MAX && src1w >= SIMM_MIN)3541PTR_FAIL_IF(push_inst(compiler, (type <= SLJIT_LESS_EQUAL ? SLTIU : SLTI) | S(src2) | T(TMP_REG1) | IMM(src1w), DR(TMP_REG1)));3542else {3543RESOLVE_IMM1();3544PTR_FAIL_IF(push_inst(compiler, (type <= SLJIT_LESS_EQUAL ? SLTU : SLT) | S(src2) | T(src1) | D(TMP_REG1), DR(TMP_REG1)));3545}3546type = (type == SLJIT_GREATER || type == SLJIT_SIG_GREATER) ? SLJIT_NOT_EQUAL : SLJIT_EQUAL;3547}35483549jump->flags |= IS_BIT26_COND;3550PTR_FAIL_IF(push_inst(compiler, (type == SLJIT_EQUAL ? BNE : BEQ) | S(TMP_REG1) | TA(0) | BRANCH_LENGTH, UNMOVABLE_INS));3551}35523553PTR_FAIL_IF(push_inst(compiler, JR | S(PIC_ADDR_REG), UNMOVABLE_INS));3554jump->addr = compiler->size;3555PTR_FAIL_IF(push_inst(compiler, NOP, UNMOVABLE_INS));35563557/* Maximum number of instructions required for generating a constant. */3558#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)3559compiler->size += 2;3560#else3561compiler->size += 6;3562#endif3563return jump;3564}35653566#undef RESOLVE_IMM13567#undef RESOLVE_IMM235683569#undef BRANCH_LENGTH3570#undef BR_Z3571#undef BR_NZ3572#undef BR_T3573#undef BR_F35743575SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_ijump(struct sljit_compiler *compiler, sljit_s32 type, sljit_s32 src, sljit_sw srcw)3576{3577struct sljit_jump *jump = NULL;35783579CHECK_ERROR();3580CHECK(check_sljit_emit_ijump(compiler, type, src, srcw));35813582if (src == SLJIT_IMM) {3583jump = (struct sljit_jump*)ensure_abuf(compiler, sizeof(struct sljit_jump));3584FAIL_IF(!jump);3585set_jump(jump, compiler, JUMP_ADDR | ((type >= SLJIT_FAST_CALL) ? IS_JAL : 0));3586jump->u.target = (sljit_uw)srcw;35873588if (compiler->delay_slot != UNMOVABLE_INS)3589jump->flags |= IS_MOVABLE;35903591src = PIC_ADDR_REG;3592} else if (src & SLJIT_MEM) {3593ADJUST_LOCAL_OFFSET(src, srcw);3594FAIL_IF(emit_op_mem(compiler, WORD_DATA | LOAD_DATA, DR(PIC_ADDR_REG), src, srcw));3595src = PIC_ADDR_REG;3596}35973598if (type <= SLJIT_JUMP)3599FAIL_IF(push_inst(compiler, JR | S(src), UNMOVABLE_INS));3600else3601FAIL_IF(push_inst(compiler, JALR | S(src) | DA(RETURN_ADDR_REG), UNMOVABLE_INS));36023603if (jump != NULL) {3604jump->addr = compiler->size;36053606/* Maximum number of instructions required for generating a constant. */3607#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)3608compiler->size += 2;3609#else3610compiler->size += 6;3611#endif3612}36133614return push_inst(compiler, NOP, UNMOVABLE_INS);3615}36163617SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_flags(struct sljit_compiler *compiler, sljit_s32 op,3618sljit_s32 dst, sljit_sw dstw,3619sljit_s32 type)3620{3621sljit_s32 src_ar, dst_ar, invert;3622sljit_s32 saved_op = op;3623#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)3624sljit_s32 mem_type = WORD_DATA;3625#else3626sljit_s32 mem_type = ((op & SLJIT_32) || op == SLJIT_MOV32) ? (INT_DATA | SIGNED_DATA) : WORD_DATA;3627#endif36283629CHECK_ERROR();3630CHECK(check_sljit_emit_op_flags(compiler, op, dst, dstw, type));3631ADJUST_LOCAL_OFFSET(dst, dstw);36323633op = GET_OPCODE(op);3634dst_ar = DR((op < SLJIT_ADD && FAST_IS_REG(dst)) ? dst : TMP_REG2);36353636compiler->cache_arg = 0;3637compiler->cache_argw = 0;36383639if (op >= SLJIT_ADD && (dst & SLJIT_MEM))3640FAIL_IF(emit_op_mem2(compiler, mem_type | LOAD_DATA, DR(TMP_REG1), dst, dstw, dst, dstw));36413642if (type < SLJIT_F_EQUAL) {3643src_ar = OTHER_FLAG;3644invert = type & 0x1;36453646switch (type) {3647case SLJIT_EQUAL:3648case SLJIT_NOT_EQUAL:3649FAIL_IF(push_inst(compiler, SLTIU | SA(EQUAL_FLAG) | TA(dst_ar) | IMM(1), dst_ar));3650src_ar = dst_ar;3651break;3652case SLJIT_OVERFLOW:3653case SLJIT_NOT_OVERFLOW:3654if (compiler->status_flags_state & (SLJIT_CURRENT_FLAGS_ADD | SLJIT_CURRENT_FLAGS_SUB)) {3655src_ar = OTHER_FLAG;3656break;3657}3658FAIL_IF(push_inst(compiler, SLTIU | SA(OTHER_FLAG) | TA(dst_ar) | IMM(1), dst_ar));3659src_ar = dst_ar;3660invert ^= 0x1;3661break;3662}3663} else {3664invert = 0;36653666switch (type) {3667case SLJIT_F_NOT_EQUAL:3668case SLJIT_F_GREATER_EQUAL:3669case SLJIT_F_GREATER:3670case SLJIT_UNORDERED_OR_NOT_EQUAL:3671case SLJIT_ORDERED_NOT_EQUAL:3672case SLJIT_UNORDERED_OR_GREATER_EQUAL:3673case SLJIT_ORDERED_GREATER_EQUAL:3674case SLJIT_ORDERED_GREATER:3675case SLJIT_UNORDERED_OR_GREATER:3676case SLJIT_ORDERED:3677invert = 1;3678break;3679}36803681#if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 6)3682FAIL_IF(push_inst(compiler, MFC1 | TA(dst_ar) | FS(TMP_FREG3), dst_ar));3683#else /* SLJIT_MIPS_REV < 6 */3684FAIL_IF(push_inst(compiler, CFC1 | TA(dst_ar) | DA(FCSR_REG), dst_ar));3685#endif /* SLJIT_MIPS_REV >= 6 */3686FAIL_IF(push_inst(compiler, SRL | TA(dst_ar) | DA(dst_ar) | SH_IMM(23), dst_ar));3687FAIL_IF(push_inst(compiler, ANDI | SA(dst_ar) | TA(dst_ar) | IMM(1), dst_ar));3688src_ar = dst_ar;3689}36903691if (invert) {3692FAIL_IF(push_inst(compiler, XORI | SA(src_ar) | TA(dst_ar) | IMM(1), dst_ar));3693src_ar = dst_ar;3694}36953696if (op < SLJIT_ADD) {3697if (dst & SLJIT_MEM)3698return emit_op_mem(compiler, mem_type, src_ar, dst, dstw);36993700if (src_ar != dst_ar)3701return push_inst(compiler, ADDU_W | SA(src_ar) | TA(0) | DA(dst_ar), dst_ar);3702return SLJIT_SUCCESS;3703}37043705/* OTHER_FLAG cannot be specified as src2 argument at the moment. */3706if (DR(TMP_REG2) != src_ar)3707FAIL_IF(push_inst(compiler, ADDU_W | SA(src_ar) | TA(0) | D(TMP_REG2), DR(TMP_REG2)));37083709mem_type |= CUMULATIVE_OP | LOGICAL_OP | IMM_OP | ALT_KEEP_CACHE;37103711if (dst & SLJIT_MEM)3712return emit_op(compiler, saved_op, mem_type, dst, dstw, TMP_REG1, 0, TMP_REG2, 0);3713return emit_op(compiler, saved_op, mem_type, dst, dstw, dst, dstw, TMP_REG2, 0);3714}37153716#if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 1 && SLJIT_MIPS_REV < 6)37173718static sljit_ins get_select_cc(sljit_s32 type, sljit_s32 is_float)3719{3720switch (type & ~SLJIT_32) {3721case SLJIT_EQUAL:3722return (is_float ? MOVZ_S : MOVZ) | TA(EQUAL_FLAG);3723case SLJIT_NOT_EQUAL:3724return (is_float ? MOVN_S : MOVN) | TA(EQUAL_FLAG);3725case SLJIT_LESS:3726case SLJIT_GREATER:3727case SLJIT_SIG_LESS:3728case SLJIT_SIG_GREATER:3729case SLJIT_OVERFLOW:3730case SLJIT_CARRY:3731return (is_float ? MOVN_S : MOVN) | TA(OTHER_FLAG);3732case SLJIT_GREATER_EQUAL:3733case SLJIT_LESS_EQUAL:3734case SLJIT_SIG_GREATER_EQUAL:3735case SLJIT_SIG_LESS_EQUAL:3736case SLJIT_NOT_OVERFLOW:3737case SLJIT_NOT_CARRY:3738return (is_float ? MOVZ_S : MOVZ) | TA(OTHER_FLAG);3739case SLJIT_F_EQUAL:3740case SLJIT_F_LESS:3741case SLJIT_F_LESS_EQUAL:3742case SLJIT_ORDERED_EQUAL:3743case SLJIT_UNORDERED_OR_EQUAL:3744case SLJIT_ORDERED_LESS:3745case SLJIT_UNORDERED_OR_LESS:3746case SLJIT_UNORDERED_OR_LESS_EQUAL:3747case SLJIT_ORDERED_LESS_EQUAL:3748case SLJIT_UNORDERED:3749return is_float ? MOVT_S : MOVT;3750case SLJIT_F_NOT_EQUAL:3751case SLJIT_F_GREATER_EQUAL:3752case SLJIT_F_GREATER:3753case SLJIT_UNORDERED_OR_NOT_EQUAL:3754case SLJIT_ORDERED_NOT_EQUAL:3755case SLJIT_UNORDERED_OR_GREATER_EQUAL:3756case SLJIT_ORDERED_GREATER_EQUAL:3757case SLJIT_ORDERED_GREATER:3758case SLJIT_UNORDERED_OR_GREATER:3759case SLJIT_ORDERED:3760return is_float ? MOVF_S : MOVF;3761default:3762SLJIT_UNREACHABLE();3763return (is_float ? MOVZ_S : MOVZ) | TA(OTHER_FLAG);3764}3765}37663767#endif /* SLJIT_MIPS_REV >= 1 */37683769SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_select(struct sljit_compiler *compiler, sljit_s32 type,3770sljit_s32 dst_reg,3771sljit_s32 src1, sljit_sw src1w,3772sljit_s32 src2_reg)3773{3774#if (defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64)3775sljit_s32 inp_flags = ((type & SLJIT_32) ? INT_DATA : WORD_DATA) | LOAD_DATA;3776sljit_ins mov_ins = (type & SLJIT_32) ? ADDU : DADDU;3777#else /* !SLJIT_CONFIG_MIPS_64 */3778sljit_s32 inp_flags = WORD_DATA | LOAD_DATA;3779sljit_ins mov_ins = ADDU;3780#endif /* SLJIT_CONFIG_MIPS_64 */37813782#if !(defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 1 && SLJIT_MIPS_REV < 6)3783struct sljit_label *label;3784struct sljit_jump *jump;3785#endif /* !(SLJIT_MIPS_REV >= 1 && SLJIT_MIPS_REV < 6) */37863787CHECK_ERROR();3788CHECK(check_sljit_emit_select(compiler, type, dst_reg, src1, src1w, src2_reg));3789ADJUST_LOCAL_OFFSET(src1, src1w);37903791#if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 1 && SLJIT_MIPS_REV < 6)3792if (src1 & SLJIT_MEM) {3793FAIL_IF(emit_op_mem(compiler, inp_flags, DR(TMP_REG1), src1, src1w));3794src1 = TMP_REG1;3795} else if (src1 == SLJIT_IMM) {3796#if (defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64)3797if (type & SLJIT_32)3798src1w = (sljit_s32)src1w;3799#endif3800FAIL_IF(load_immediate(compiler, DR(TMP_REG1), src1w));3801src1 = TMP_REG1;3802}38033804if (dst_reg != src2_reg) {3805if (dst_reg == src1) {3806src1 = src2_reg;3807type ^= 0x1;3808} else3809FAIL_IF(push_inst(compiler, mov_ins | S(src2_reg) | TA(0) | D(dst_reg), DR(dst_reg)));3810}38113812return push_inst(compiler, get_select_cc(type, 0) | S(src1) | D(dst_reg), DR(dst_reg));38133814#else /* SLJIT_MIPS_REV < 1 || SLJIT_MIPS_REV >= 6 */3815if (dst_reg != src2_reg) {3816if (dst_reg == src1) {3817src1 = src2_reg;3818src1w = 0;3819type ^= 0x1;3820} else {3821if (ADDRESSING_DEPENDS_ON(src1, dst_reg)) {3822FAIL_IF(push_inst(compiler, ADDU_W | S(dst_reg) | TA(0) | D(TMP_REG1), DR(TMP_REG1)));38233824if ((src1 & REG_MASK) == dst_reg)3825src1 = (src1 & ~REG_MASK) | TMP_REG1;38263827if (OFFS_REG(src1) == dst_reg)3828src1 = (src1 & ~OFFS_REG_MASK) | TO_OFFS_REG(TMP_REG1);3829}38303831FAIL_IF(push_inst(compiler, mov_ins | S(src2_reg) | TA(0) | D(dst_reg), DR(dst_reg)));3832}3833}38343835SLJIT_SKIP_CHECKS(compiler);3836jump = sljit_emit_jump(compiler, (type & ~SLJIT_32) ^ 0x1);3837FAIL_IF(!jump);38383839if (src1 & SLJIT_MEM) {3840FAIL_IF(emit_op_mem(compiler, inp_flags, DR(dst_reg), src1, src1w));3841} else if (src1 == SLJIT_IMM) {3842#if (defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64)3843if (type & SLJIT_32)3844src1w = (sljit_s32)src1w;3845#endif /* SLJIT_CONFIG_MIPS_64 */3846FAIL_IF(load_immediate(compiler, DR(dst_reg), src1w));3847} else3848FAIL_IF(push_inst(compiler, mov_ins | S(src1) | TA(0) | D(dst_reg), DR(dst_reg)));38493850SLJIT_SKIP_CHECKS(compiler);3851label = sljit_emit_label(compiler);3852FAIL_IF(!label);38533854sljit_set_label(jump, label);3855return SLJIT_SUCCESS;3856#endif /* SLJIT_MIPS_REV >= 1 */3857}38583859SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fselect(struct sljit_compiler *compiler, sljit_s32 type,3860sljit_s32 dst_freg,3861sljit_s32 src1, sljit_sw src1w,3862sljit_s32 src2_freg)3863{3864#if !(defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 1 && SLJIT_MIPS_REV < 6)3865struct sljit_label *label;3866struct sljit_jump *jump;3867#endif /* !(SLJIT_MIPS_REV >= 1 && SLJIT_MIPS_REV < 6) */38683869CHECK_ERROR();3870CHECK(check_sljit_emit_fselect(compiler, type, dst_freg, src1, src1w, src2_freg));38713872ADJUST_LOCAL_OFFSET(src1, src1w);38733874if (dst_freg != src2_freg) {3875if (dst_freg == src1) {3876src1 = src2_freg;3877src1w = 0;3878type ^= 0x1;3879} else3880FAIL_IF(push_inst(compiler, MOV_fmt(FMT(type)) | FS(src2_freg) | FD(dst_freg), MOVABLE_INS));3881}38823883#if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 1 && SLJIT_MIPS_REV < 6)3884if (src1 & SLJIT_MEM) {3885FAIL_IF(emit_op_mem(compiler, FLOAT_DATA(type) | LOAD_DATA, FR(TMP_FREG2), src1, src1w));3886src1 = TMP_FREG2;3887}38883889return push_inst(compiler, get_select_cc(type, 1) | FMT(type) | FS(src1) | FD(dst_freg), MOVABLE_INS);38903891#else /* SLJIT_MIPS_REV < 1 || SLJIT_MIPS_REV >= 6 */3892SLJIT_SKIP_CHECKS(compiler);3893jump = sljit_emit_jump(compiler, (type & ~SLJIT_32) ^ 0x1);3894FAIL_IF(!jump);38953896if (src1 & SLJIT_MEM)3897FAIL_IF(emit_op_mem(compiler, FLOAT_DATA(type) | LOAD_DATA, FR(dst_freg), src1, src1w));3898else3899FAIL_IF(push_inst(compiler, MOV_fmt(FMT(type)) | FS(src1) | FD(dst_freg), MOVABLE_INS));39003901SLJIT_SKIP_CHECKS(compiler);3902label = sljit_emit_label(compiler);3903FAIL_IF(!label);39043905sljit_set_label(jump, label);3906return SLJIT_SUCCESS;3907#endif /* SLJIT_MIPS_REV >= 1 */3908}39093910#undef FLOAT_DATA3911#undef FMT39123913static sljit_s32 update_mem_addr(struct sljit_compiler *compiler, sljit_s32 *mem, sljit_sw *memw, sljit_s16 max_offset)3914{3915sljit_s32 arg = *mem;3916sljit_sw argw = *memw;39173918if (SLJIT_UNLIKELY(arg & OFFS_REG_MASK)) {3919argw &= 0x3;39203921if (SLJIT_UNLIKELY(argw)) {3922FAIL_IF(push_inst(compiler, SLL_W | T(OFFS_REG(arg)) | D(TMP_REG1) | SH_IMM(argw), DR(TMP_REG1)));3923FAIL_IF(push_inst(compiler, ADDU_W | S(TMP_REG1) | T(arg & REG_MASK) | D(TMP_REG1), DR(TMP_REG1)));3924} else3925FAIL_IF(push_inst(compiler, ADDU_W | S(arg & REG_MASK) | T(OFFS_REG(arg)) | D(TMP_REG1), DR(TMP_REG1)));39263927*mem = TMP_REG1;3928*memw = 0;39293930return SLJIT_SUCCESS;3931}39323933if (argw <= max_offset && argw >= SIMM_MIN) {3934*mem = arg & REG_MASK;3935return SLJIT_SUCCESS;3936}39373938*mem = TMP_REG1;39393940if ((sljit_s16)argw > max_offset) {3941FAIL_IF(load_immediate(compiler, DR(TMP_REG1), argw));3942*memw = 0;3943} else {3944FAIL_IF(load_immediate(compiler, DR(TMP_REG1), TO_ARGW_HI(argw)));3945*memw = (sljit_s16)argw;3946}39473948if ((arg & REG_MASK) == 0)3949return SLJIT_SUCCESS;39503951return push_inst(compiler, ADDU_W | S(TMP_REG1) | T(arg & REG_MASK) | D(TMP_REG1), DR(TMP_REG1));3952}39533954#if (defined SLJIT_LITTLE_ENDIAN && SLJIT_LITTLE_ENDIAN)3955#define IMM_LEFT(memw) IMM((memw) + SSIZE_OF(sw) - 1)3956#define IMM_RIGHT(memw) IMM(memw)3957#define IMM_32_LEFT(memw) IMM((memw) + SSIZE_OF(s32) - 1)3958#define IMM_32_RIGHT(memw) IMM(memw)3959#define IMM_F64_FIRST_LEFT(memw) IMM((memw) + SSIZE_OF(s32) - 1)3960#define IMM_F64_FIRST_RIGHT(memw) IMM(memw)3961#define IMM_F64_SECOND_LEFT(memw) IMM((memw) + SSIZE_OF(f64) - 1)3962#define IMM_F64_SECOND_RIGHT(memw) IMM((memw) + SSIZE_OF(s32))3963#define IMM_16_FIRST(memw) IMM((memw) + 1)3964#define IMM_16_SECOND(memw) IMM(memw)3965#else /* !SLJIT_LITTLE_ENDIAN */3966#define IMM_LEFT(memw) IMM(memw)3967#define IMM_RIGHT(memw) IMM((memw) + SSIZE_OF(sw) - 1)3968#define IMM_32_LEFT(memw) IMM(memw)3969#define IMM_32_RIGHT(memw) IMM((memw) + SSIZE_OF(s32) - 1)3970#define IMM_F64_FIRST_LEFT(memw) IMM((memw) + SSIZE_OF(s32))3971#define IMM_F64_FIRST_RIGHT(memw) IMM((memw) + SSIZE_OF(f64) - 1)3972#define IMM_F64_SECOND_LEFT(memw) IMM(memw)3973#define IMM_F64_SECOND_RIGHT(memw) IMM((memw) + SSIZE_OF(s32) - 1)3974#define IMM_16_FIRST(memw) IMM(memw)3975#define IMM_16_SECOND(memw) IMM((memw) + 1)3976#endif /* SLJIT_LITTLE_ENDIAN */39773978#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)3979#define MEM_CHECK_UNALIGNED(type) ((type) & (SLJIT_MEM_UNALIGNED | SLJIT_MEM_ALIGNED_16))3980#else /* !SLJIT_CONFIG_MIPS_32 */3981#define MEM_CHECK_UNALIGNED(type) ((type) & (SLJIT_MEM_UNALIGNED | SLJIT_MEM_ALIGNED_16 | SLJIT_MEM_ALIGNED_32))3982#endif /* SLJIT_CONFIG_MIPS_32 */39833984SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_mem(struct sljit_compiler *compiler, sljit_s32 type,3985sljit_s32 reg,3986sljit_s32 mem, sljit_sw memw)3987{3988sljit_s32 op = type & 0xff;3989sljit_s32 flags = 0;3990sljit_ins ins;3991#if !(defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 6)3992sljit_ins ins_right;3993#endif /* !(SLJIT_MIPS_REV >= 6) */39943995CHECK_ERROR();3996CHECK(check_sljit_emit_mem(compiler, type, reg, mem, memw));39973998if (reg & REG_PAIR_MASK) {3999ADJUST_LOCAL_OFFSET(mem, memw);40004001#if !(defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 6)4002if (MEM_CHECK_UNALIGNED(type)) {4003FAIL_IF(update_mem_addr(compiler, &mem, &memw, SIMM_MAX - (2 * SSIZE_OF(sw) - 1)));40044005if (!(type & SLJIT_MEM_STORE) && (mem == REG_PAIR_FIRST(reg) || mem == REG_PAIR_SECOND(reg))) {4006FAIL_IF(push_inst(compiler, ADDU_W | S(mem) | TA(0) | D(TMP_REG1), DR(TMP_REG1)));4007mem = TMP_REG1;4008}40094010#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)4011ins = ((type & SLJIT_MEM_STORE) ? SWL : LWL) | S(mem);4012ins_right = ((type & SLJIT_MEM_STORE) ? SWR : LWR) | S(mem);4013#else /* !SLJIT_CONFIG_MIPS_32 */4014ins = ((type & SLJIT_MEM_STORE) ? SDL : LDL) | S(mem);4015ins_right = ((type & SLJIT_MEM_STORE) ? SDR : LDR) | S(mem);4016#endif /* SLJIT_CONFIG_MIPS_32 */40174018FAIL_IF(push_inst(compiler, ins | T(REG_PAIR_FIRST(reg)) | IMM_LEFT(memw), DR(REG_PAIR_FIRST(reg))));4019FAIL_IF(push_inst(compiler, ins_right | T(REG_PAIR_FIRST(reg)) | IMM_RIGHT(memw), DR(REG_PAIR_FIRST(reg))));4020FAIL_IF(push_inst(compiler, ins | T(REG_PAIR_SECOND(reg)) | IMM_LEFT(memw + SSIZE_OF(sw)), DR(REG_PAIR_SECOND(reg))));4021return push_inst(compiler, ins_right | T(REG_PAIR_SECOND(reg)) | IMM_RIGHT(memw + SSIZE_OF(sw)), DR(REG_PAIR_SECOND(reg)));4022}4023#endif /* !(SLJIT_MIPS_REV >= 6) */40244025FAIL_IF(update_mem_addr(compiler, &mem, &memw, SIMM_MAX - SSIZE_OF(sw)));40264027ins = ((type & SLJIT_MEM_STORE) ? STORE_W : LOAD_W) | S(mem);40284029if (!(type & SLJIT_MEM_STORE) && mem == REG_PAIR_FIRST(reg)) {4030FAIL_IF(push_inst(compiler, ins | T(REG_PAIR_SECOND(reg)) | IMM(memw + SSIZE_OF(sw)), DR(REG_PAIR_SECOND(reg))));4031return push_inst(compiler, ins | T(REG_PAIR_FIRST(reg)) | IMM(memw), DR(REG_PAIR_FIRST(reg)));4032}40334034FAIL_IF(push_inst(compiler, ins | T(REG_PAIR_FIRST(reg)) | IMM(memw), DR(REG_PAIR_FIRST(reg))));4035return push_inst(compiler, ins | T(REG_PAIR_SECOND(reg)) | IMM(memw + SSIZE_OF(sw)), DR(REG_PAIR_SECOND(reg)));4036}40374038#if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 6)4039return sljit_emit_mem_unaligned(compiler, type, reg, mem, memw);4040#else /* !(SLJIT_MIPS_REV >= 6) */4041ADJUST_LOCAL_OFFSET(mem, memw);40424043switch (op) {4044case SLJIT_MOV_U8:4045case SLJIT_MOV_S8:4046flags = BYTE_DATA;4047if (!(type & SLJIT_MEM_STORE))4048flags |= LOAD_DATA;40494050if (op == SLJIT_MOV_S8)4051flags |= SIGNED_DATA;40524053return emit_op_mem(compiler, flags, DR(reg), mem, memw);40544055case SLJIT_MOV_U16:4056case SLJIT_MOV_S16:4057FAIL_IF(update_mem_addr(compiler, &mem, &memw, SIMM_MAX - 1));4058SLJIT_ASSERT(FAST_IS_REG(mem) && mem != TMP_REG2);40594060if (type & SLJIT_MEM_STORE) {4061FAIL_IF(push_inst(compiler, SRA_W | T(reg) | D(TMP_REG2) | SH_IMM(8), DR(TMP_REG2)));4062FAIL_IF(push_inst(compiler, data_transfer_insts[BYTE_DATA] | S(mem) | T(TMP_REG2) | IMM_16_FIRST(memw), MOVABLE_INS));4063return push_inst(compiler, data_transfer_insts[BYTE_DATA] | S(mem) | T(reg) | IMM_16_SECOND(memw), MOVABLE_INS);4064}40654066flags = BYTE_DATA | LOAD_DATA;40674068if (op == SLJIT_MOV_S16)4069flags |= SIGNED_DATA;40704071FAIL_IF(push_inst(compiler, data_transfer_insts[flags] | S(mem) | T(TMP_REG2) | IMM_16_FIRST(memw), DR(TMP_REG2)));4072FAIL_IF(push_inst(compiler, data_transfer_insts[BYTE_DATA | LOAD_DATA] | S(mem) | T(reg) | IMM_16_SECOND(memw), DR(reg)));4073FAIL_IF(push_inst(compiler, SLL_W | T(TMP_REG2) | D(TMP_REG2) | SH_IMM(8), DR(TMP_REG2)));4074return push_inst(compiler, OR | S(reg) | T(TMP_REG2) | D(reg), DR(reg));40754076case SLJIT_MOV:4077case SLJIT_MOV_P:4078#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)4079if (type & SLJIT_MEM_ALIGNED_32) {4080flags = WORD_DATA;4081if (!(type & SLJIT_MEM_STORE))4082flags |= LOAD_DATA;40834084return emit_op_mem(compiler, flags, DR(reg), mem, memw);4085}4086#else /* !SLJIT_CONFIG_MIPS_32 */4087FAIL_IF(update_mem_addr(compiler, &mem, &memw, SIMM_MAX - 7));4088SLJIT_ASSERT(FAST_IS_REG(mem) && mem != TMP_REG2);40894090if (type & SLJIT_MEM_STORE) {4091FAIL_IF(push_inst(compiler, SDL | S(mem) | T(reg) | IMM_LEFT(memw), MOVABLE_INS));4092return push_inst(compiler, SDR | S(mem) | T(reg) | IMM_RIGHT(memw), MOVABLE_INS);4093}40944095if (mem == reg) {4096FAIL_IF(push_inst(compiler, ADDU_W | S(mem) | TA(0) | D(TMP_REG1), DR(TMP_REG1)));4097mem = TMP_REG1;4098}40994100FAIL_IF(push_inst(compiler, LDL | S(mem) | T(reg) | IMM_LEFT(memw), DR(reg)));4101return push_inst(compiler, LDR | S(mem) | T(reg) | IMM_RIGHT(memw), DR(reg));4102#endif /* SLJIT_CONFIG_MIPS_32 */4103}41044105FAIL_IF(update_mem_addr(compiler, &mem, &memw, SIMM_MAX - 3));4106SLJIT_ASSERT(FAST_IS_REG(mem) && mem != TMP_REG2);41074108if (type & SLJIT_MEM_STORE) {4109FAIL_IF(push_inst(compiler, SWL | S(mem) | T(reg) | IMM_32_LEFT(memw), MOVABLE_INS));4110return push_inst(compiler, SWR | S(mem) | T(reg) | IMM_32_RIGHT(memw), MOVABLE_INS);4111}41124113if (mem == reg) {4114FAIL_IF(push_inst(compiler, ADDU_W | S(mem) | TA(0) | D(TMP_REG1), DR(TMP_REG1)));4115mem = TMP_REG1;4116}41174118FAIL_IF(push_inst(compiler, LWL | S(mem) | T(reg) | IMM_32_LEFT(memw), DR(reg)));4119#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)4120return push_inst(compiler, LWR | S(mem) | T(reg) | IMM_32_RIGHT(memw), DR(reg));4121#else /* !SLJIT_CONFIG_MIPS_32 */4122FAIL_IF(push_inst(compiler, LWR | S(mem) | T(reg) | IMM_32_RIGHT(memw), DR(reg)));41234124if (op != SLJIT_MOV_U32)4125return SLJIT_SUCCESS;41264127#if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 2)4128return push_inst(compiler, DINSU | T(reg) | SA(0) | (31 << 11), DR(reg));4129#else /* SLJIT_MIPS_REV < 2 */4130FAIL_IF(push_inst(compiler, DSLL32 | T(reg) | D(reg) | SH_IMM(0), DR(reg)));4131return push_inst(compiler, DSRL32 | T(reg) | D(reg) | SH_IMM(0), DR(reg));4132#endif /* SLJIT_MIPS_REV >= 2 */4133#endif /* SLJIT_CONFIG_MIPS_32 */4134#endif /* SLJIT_MIPS_REV >= 6 */4135}41364137#if !(defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 6)41384139SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fmem(struct sljit_compiler *compiler, sljit_s32 type,4140sljit_s32 freg,4141sljit_s32 mem, sljit_sw memw)4142{4143CHECK_ERROR();4144CHECK(check_sljit_emit_fmem(compiler, type, freg, mem, memw));41454146FAIL_IF(update_mem_addr(compiler, &mem, &memw, SIMM_MAX - (type & SLJIT_32) ? 3 : 7));4147SLJIT_ASSERT(FAST_IS_REG(mem) && mem != TMP_REG2);41484149if (type & SLJIT_MEM_STORE) {4150if (type & SLJIT_32) {4151FAIL_IF(push_inst(compiler, MFC1 | T(TMP_REG2) | FS(freg), DR(TMP_REG2)));4152#if !defined(SLJIT_MIPS_REV) || (SLJIT_CONFIG_MIPS_32 && SLJIT_MIPS_REV <= 1)4153FAIL_IF(push_inst(compiler, NOP, UNMOVABLE_INS));4154#endif /* MIPS III */4155FAIL_IF(push_inst(compiler, SWL | S(mem) | T(TMP_REG2) | IMM_32_LEFT(memw), MOVABLE_INS));4156return push_inst(compiler, SWR | S(mem) | T(TMP_REG2) | IMM_32_RIGHT(memw), MOVABLE_INS);4157}41584159#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)4160FAIL_IF(push_inst(compiler, MFC1 | T(TMP_REG2) | FS(freg), DR(TMP_REG2)));4161#if !defined(SLJIT_MIPS_REV) || SLJIT_MIPS_REV <= 14162FAIL_IF(push_inst(compiler, NOP, UNMOVABLE_INS));4163#endif /* MIPS III */4164FAIL_IF(push_inst(compiler, SWL | S(mem) | T(TMP_REG2) | IMM_F64_FIRST_LEFT(memw), MOVABLE_INS));4165FAIL_IF(push_inst(compiler, SWR | S(mem) | T(TMP_REG2) | IMM_F64_FIRST_RIGHT(memw), MOVABLE_INS));4166switch (cpu_feature_list & CPU_FEATURE_FR) {4167#if defined(SLJIT_MIPS_REV) && SLJIT_MIPS_REV >= 24168case CPU_FEATURE_FR:4169FAIL_IF(push_inst(compiler, MFHC1 | T(TMP_REG2) | FS(freg), DR(TMP_REG2)));4170break;4171#endif /* SLJIT_MIPS_REV >= 2 */4172default:4173FAIL_IF(push_inst(compiler, MFC1 | T(TMP_REG2) | FS(freg) | (1 << 11), DR(TMP_REG2)));4174#if !defined(SLJIT_MIPS_REV) || SLJIT_MIPS_REV <= 14175FAIL_IF(push_inst(compiler, NOP, UNMOVABLE_INS));4176#endif4177break;4178}41794180FAIL_IF(push_inst(compiler, SWL | S(mem) | T(TMP_REG2) | IMM_F64_SECOND_LEFT(memw), MOVABLE_INS));4181return push_inst(compiler, SWR | S(mem) | T(TMP_REG2) | IMM_F64_SECOND_RIGHT(memw), MOVABLE_INS);4182#else /* !SLJIT_CONFIG_MIPS_32 */4183FAIL_IF(push_inst(compiler, DMFC1 | T(TMP_REG2) | FS(freg), DR(TMP_REG2)));4184#if !defined(SLJIT_MIPS_REV) || SLJIT_MIPS_REV <= 14185FAIL_IF(push_inst(compiler, NOP, UNMOVABLE_INS));4186#endif /* MIPS III */4187FAIL_IF(push_inst(compiler, SDL | S(mem) | T(TMP_REG2) | IMM_LEFT(memw), MOVABLE_INS));4188return push_inst(compiler, SDR | S(mem) | T(TMP_REG2) | IMM_RIGHT(memw), MOVABLE_INS);4189#endif /* SLJIT_CONFIG_MIPS_32 */4190}41914192if (type & SLJIT_32) {4193FAIL_IF(push_inst(compiler, LWL | S(mem) | T(TMP_REG2) | IMM_32_LEFT(memw), DR(TMP_REG2)));4194FAIL_IF(push_inst(compiler, LWR | S(mem) | T(TMP_REG2) | IMM_32_RIGHT(memw), DR(TMP_REG2)));41954196FAIL_IF(push_inst(compiler, MTC1 | T(TMP_REG2) | FS(freg), MOVABLE_INS));4197#if !defined(SLJIT_MIPS_REV) || (SLJIT_CONFIG_MIPS_32 && SLJIT_MIPS_REV <= 1)4198FAIL_IF(push_inst(compiler, NOP, UNMOVABLE_INS));4199#endif /* MIPS III */4200return SLJIT_SUCCESS;4201}42024203#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)4204FAIL_IF(push_inst(compiler, LWL | S(mem) | T(TMP_REG2) | IMM_F64_FIRST_LEFT(memw), DR(TMP_REG2)));4205FAIL_IF(push_inst(compiler, LWR | S(mem) | T(TMP_REG2) | IMM_F64_FIRST_RIGHT(memw), DR(TMP_REG2)));4206FAIL_IF(push_inst(compiler, MTC1 | T(TMP_REG2) | FS(freg), MOVABLE_INS));42074208FAIL_IF(push_inst(compiler, LWL | S(mem) | T(TMP_REG2) | IMM_F64_SECOND_LEFT(memw), DR(TMP_REG2)));4209FAIL_IF(push_inst(compiler, LWR | S(mem) | T(TMP_REG2) | IMM_F64_SECOND_RIGHT(memw), DR(TMP_REG2)));4210switch (cpu_feature_list & CPU_FEATURE_FR) {4211#if defined(SLJIT_MIPS_REV) && SLJIT_MIPS_REV >= 24212case CPU_FEATURE_FR:4213return push_inst(compiler, MTHC1 | T(TMP_REG2) | FS(freg), MOVABLE_INS);4214#endif /* SLJIT_MIPS_REV >= 2 */4215default:4216FAIL_IF(push_inst(compiler, MTC1 | T(TMP_REG2) | FS(freg) | (1 << 11), MOVABLE_INS));4217break;4218}4219#else /* !SLJIT_CONFIG_MIPS_32 */4220FAIL_IF(push_inst(compiler, LDL | S(mem) | T(TMP_REG2) | IMM_LEFT(memw), DR(TMP_REG2)));4221FAIL_IF(push_inst(compiler, LDR | S(mem) | T(TMP_REG2) | IMM_RIGHT(memw), DR(TMP_REG2)));42224223FAIL_IF(push_inst(compiler, DMTC1 | T(TMP_REG2) | FS(freg), MOVABLE_INS));4224#endif /* SLJIT_CONFIG_MIPS_32 */4225#if !defined(SLJIT_MIPS_REV) || SLJIT_MIPS_REV <= 14226FAIL_IF(push_inst(compiler, NOP, UNMOVABLE_INS));4227#endif /* MIPS III */4228return SLJIT_SUCCESS;4229}42304231#endif /* !SLJIT_MIPS_REV || SLJIT_MIPS_REV < 6 */42324233#undef IMM_16_SECOND4234#undef IMM_16_FIRST4235#undef IMM_F64_SECOND_RIGHT4236#undef IMM_F64_SECOND_LEFT4237#undef IMM_F64_FIRST_RIGHT4238#undef IMM_F64_FIRST_LEFT4239#undef IMM_32_RIGHT4240#undef IMM_32_LEFT4241#undef IMM_RIGHT4242#undef IMM_LEFT4243#undef MEM_CHECK_UNALIGNED42444245#undef TO_ARGW_HI42464247SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_atomic_load(struct sljit_compiler *compiler, sljit_s32 op,4248sljit_s32 dst_reg,4249sljit_s32 mem_reg)4250{4251sljit_ins ins;42524253CHECK_ERROR();4254CHECK(check_sljit_emit_atomic_load(compiler, op, dst_reg, mem_reg));42554256if (op & SLJIT_ATOMIC_USE_CAS)4257return SLJIT_ERR_UNSUPPORTED;42584259switch (GET_OPCODE(op)) {4260case SLJIT_MOV:4261case SLJIT_MOV_P:4262#if (defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64)4263ins = LLD;4264break;4265#endif /* SLJIT_CONFIG_MIPS_64 */4266case SLJIT_MOV_S32:4267case SLJIT_MOV32:4268ins = LL;4269break;42704271default:4272return SLJIT_ERR_UNSUPPORTED;4273}42744275if (op & SLJIT_ATOMIC_TEST)4276return SLJIT_SUCCESS;42774278return push_inst(compiler, ins | T(dst_reg) | S(mem_reg), DR(dst_reg));4279}42804281SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_atomic_store(struct sljit_compiler *compiler, sljit_s32 op,4282sljit_s32 src_reg,4283sljit_s32 mem_reg,4284sljit_s32 temp_reg)4285{4286sljit_ins ins;42874288/* temp_reg == mem_reg is undefined so use another temp register */4289SLJIT_UNUSED_ARG(temp_reg);42904291CHECK_ERROR();4292CHECK(check_sljit_emit_atomic_store(compiler, op, src_reg, mem_reg, temp_reg));42934294if (op & SLJIT_ATOMIC_USE_CAS)4295return SLJIT_ERR_UNSUPPORTED;42964297switch (GET_OPCODE(op)) {4298case SLJIT_MOV:4299case SLJIT_MOV_P:4300#if (defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64)4301ins = SCD;4302break;4303#endif /* SLJIT_CONFIG_RISCV_64 */4304case SLJIT_MOV_S32:4305case SLJIT_MOV32:4306op |= SLJIT_32;4307ins = SC;4308break;43094310default:4311return SLJIT_ERR_UNSUPPORTED;4312}43134314if (op & SLJIT_ATOMIC_TEST)4315return SLJIT_SUCCESS;43164317FAIL_IF(push_inst(compiler, SELECT_OP(DADDU, ADDU) | S(src_reg) | TA(0) | DA(OTHER_FLAG), OTHER_FLAG));4318return push_inst(compiler, ins | TA(OTHER_FLAG) | S(mem_reg), OTHER_FLAG);4319}43204321SLJIT_API_FUNC_ATTRIBUTE struct sljit_const* sljit_emit_const(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw dstw, sljit_sw init_value)4322{4323struct sljit_const *const_;4324sljit_s32 dst_r;43254326CHECK_ERROR_PTR();4327CHECK_PTR(check_sljit_emit_const(compiler, dst, dstw, init_value));4328ADJUST_LOCAL_OFFSET(dst, dstw);43294330const_ = (struct sljit_const*)ensure_abuf(compiler, sizeof(struct sljit_const));4331PTR_FAIL_IF(!const_);4332set_const(const_, compiler);43334334dst_r = FAST_IS_REG(dst) ? dst : TMP_REG2;4335PTR_FAIL_IF(emit_const(compiler, dst_r, init_value));43364337if (dst & SLJIT_MEM)4338PTR_FAIL_IF(emit_op_mem(compiler, WORD_DATA, DR(TMP_REG2), dst, dstw));43394340return const_;4341}43424343SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_mov_addr(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw dstw)4344{4345struct sljit_jump *jump;4346sljit_s32 dst_r;43474348CHECK_ERROR_PTR();4349CHECK_PTR(check_sljit_emit_mov_addr(compiler, dst, dstw));4350ADJUST_LOCAL_OFFSET(dst, dstw);43514352jump = (struct sljit_jump*)ensure_abuf(compiler, sizeof(struct sljit_jump));4353PTR_FAIL_IF(!jump);4354set_mov_addr(jump, compiler, 0);43554356dst_r = FAST_IS_REG(dst) ? dst : TMP_REG2;4357PTR_FAIL_IF(push_inst(compiler, (sljit_ins)dst_r, UNMOVABLE_INS));4358#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)4359compiler->size += 1;4360#else4361compiler->size += 5;4362#endif43634364if (dst & SLJIT_MEM)4365PTR_FAIL_IF(emit_op_mem(compiler, WORD_DATA, DR(TMP_REG2), dst, dstw));43664367return jump;4368}436943704371