Path: blob/master/thirdparty/pcre2/deps/sljit/sljit_src/sljitNativeMIPS_common.c
22240 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/* Instruction 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}710711static SLJIT_INLINE sljit_ins *process_extended_label(sljit_ins *code_ptr, struct sljit_extended_label *ext_label)712{713SLJIT_ASSERT(ext_label->label.u.index == SLJIT_LABEL_ALIGNED);714return (sljit_ins*)((sljit_uw)code_ptr & ~(ext_label->data));715}716717SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compiler, sljit_s32 options, void *exec_allocator_data)718{719struct sljit_memory_fragment *buf;720sljit_ins *code;721sljit_ins *code_ptr;722sljit_ins *buf_ptr;723sljit_ins *buf_end;724sljit_uw word_count;725SLJIT_NEXT_DEFINE_TYPES;726sljit_sw executable_offset;727sljit_uw addr;728struct sljit_label *label;729struct sljit_jump *jump;730struct sljit_const *const_;731732CHECK_ERROR_PTR();733CHECK_PTR(check_sljit_generate_code(compiler, options));734reverse_buf(compiler);735736code = (sljit_ins*)allocate_executable_memory(compiler->size * sizeof(sljit_ins), options, exec_allocator_data, &executable_offset);737PTR_FAIL_WITH_EXEC_IF(code);738buf = compiler->buf;739740code_ptr = code;741word_count = 0;742label = compiler->labels;743jump = compiler->jumps;744const_ = compiler->consts;745SLJIT_NEXT_INIT_TYPES();746SLJIT_GET_NEXT_MIN();747748do {749buf_ptr = (sljit_ins*)buf->memory;750buf_end = buf_ptr + (buf->used_size >> 2);751do {752*code_ptr = *buf_ptr++;753if (next_min_addr == word_count) {754SLJIT_ASSERT(!label || label->size >= word_count);755SLJIT_ASSERT(!jump || jump->addr >= word_count);756SLJIT_ASSERT(!const_ || const_->addr >= word_count);757758/* These structures are ordered by their address. */759if (next_min_addr == next_label_size) {760if (label->u.index >= SLJIT_LABEL_ALIGNED) {761code_ptr = process_extended_label(code_ptr, (struct sljit_extended_label*)label);762*code_ptr = buf_ptr[-1];763}764765label->u.addr = (sljit_uw)SLJIT_ADD_EXEC_OFFSET(code_ptr, executable_offset);766label->size = (sljit_uw)(code_ptr - code);767label = label->next;768next_label_size = SLJIT_GET_NEXT_SIZE(label);769}770771if (next_min_addr == next_jump_addr) {772if (!(jump->flags & JUMP_MOV_ADDR)) {773#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)774word_count += 2;775#else /* !SLJIT_CONFIG_MIPS_32 */776word_count += 6;777#endif /* SLJIT_CONFIG_MIPS_32 */778jump->addr = (sljit_uw)(code_ptr - 1);779code_ptr = detect_jump_type(jump, code, executable_offset);780} else {781jump->addr = (sljit_uw)code_ptr;782#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)783code_ptr += 1;784word_count += 1;785#else /* !SLJIT_CONFIG_MIPS_32 */786code_ptr += mov_addr_get_length(jump, code, executable_offset);787word_count += 5;788#endif /* SLJIT_CONFIG_MIPS_32 */789}790791jump = jump->next;792next_jump_addr = SLJIT_GET_NEXT_ADDRESS(jump);793} else if (next_min_addr == next_const_addr) {794const_->addr = (sljit_uw)code_ptr;795const_ = const_->next;796next_const_addr = SLJIT_GET_NEXT_ADDRESS(const_);797}798799SLJIT_GET_NEXT_MIN();800}801code_ptr++;802word_count++;803} while (buf_ptr < buf_end);804805buf = buf->next;806} while (buf);807808if (label && label->size == word_count) {809if (label->u.index >= SLJIT_LABEL_ALIGNED)810code_ptr = process_extended_label(code_ptr, (struct sljit_extended_label*)label);811812label->u.addr = (sljit_uw)code_ptr;813label->size = (sljit_uw)(code_ptr - code);814label = label->next;815}816817SLJIT_ASSERT(!label);818SLJIT_ASSERT(!jump);819SLJIT_ASSERT(!const_);820SLJIT_ASSERT(code_ptr - code <= (sljit_sw)compiler->size);821822jump = compiler->jumps;823while (jump) {824do {825addr = (jump->flags & JUMP_ADDR) ? jump->u.target : jump->u.label->u.addr;826buf_ptr = (sljit_ins *)jump->addr;827828if (jump->flags & PATCH_B) {829addr = (sljit_uw)((sljit_sw)(addr - (sljit_uw)SLJIT_ADD_EXEC_OFFSET(buf_ptr, executable_offset) - sizeof(sljit_ins)) >> 2);830SLJIT_ASSERT((sljit_sw)addr <= SIMM_MAX && (sljit_sw)addr >= SIMM_MIN);831buf_ptr[0] = (buf_ptr[0] & 0xffff0000) | ((sljit_ins)addr & 0xffff);832break;833}834if (jump->flags & PATCH_J) {835SLJIT_ASSERT((addr & ~(sljit_uw)0xfffffff)836== (((sljit_uw)SLJIT_ADD_EXEC_OFFSET(buf_ptr, executable_offset) + sizeof(sljit_ins)) & ~(sljit_uw)0xfffffff));837buf_ptr[0] |= (sljit_ins)(addr >> 2) & 0x03ffffff;838break;839}840841load_addr_to_reg(jump);842} while (0);843844jump = jump->next;845}846847compiler->error = SLJIT_ERR_COMPILED;848compiler->executable_offset = executable_offset;849compiler->executable_size = (sljit_uw)(code_ptr - code) * sizeof(sljit_ins);850851code = (sljit_ins *)SLJIT_ADD_EXEC_OFFSET(code, executable_offset);852code_ptr = (sljit_ins *)SLJIT_ADD_EXEC_OFFSET(code_ptr, executable_offset);853854#ifndef __GNUC__855SLJIT_CACHE_FLUSH(code, code_ptr);856#else857/* GCC workaround for invalid code generation with -O2. */858sljit_cache_flush(code, code_ptr);859#endif860SLJIT_UPDATE_WX_FLAGS(code, code_ptr, 1);861return code;862}863864SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_has_cpu_feature(sljit_s32 feature_type)865{866switch (feature_type) {867#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32) \868&& (!defined(SLJIT_IS_FPU_AVAILABLE) || SLJIT_IS_FPU_AVAILABLE)869case SLJIT_HAS_F64_AS_F32_PAIR:870if (!cpu_feature_list)871get_cpu_features();872873return (cpu_feature_list & CPU_FEATURE_FR) != 0;874#endif /* SLJIT_CONFIG_MIPS_32 && SLJIT_IS_FPU_AVAILABLE */875case SLJIT_HAS_FPU:876if (!cpu_feature_list)877get_cpu_features();878879return (cpu_feature_list & CPU_FEATURE_FPU) != 0;880case SLJIT_HAS_ZERO_REGISTER:881case SLJIT_HAS_COPY_F32:882case SLJIT_HAS_COPY_F64:883return 1;884#if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 1)885case SLJIT_HAS_CLZ:886case SLJIT_HAS_CMOV:887case SLJIT_HAS_PREFETCH:888case SLJIT_HAS_ATOMIC:889case SLJIT_HAS_MEMORY_BARRIER:890return 1;891892case SLJIT_HAS_CTZ:893return 2;894#endif /* SLJIT_MIPS_REV >= 1 */895#if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 2)896case SLJIT_HAS_REV:897case SLJIT_HAS_ROT:898return 1;899#endif /* SLJIT_MIPS_REV >= 2 */900default:901return 0;902}903}904905SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_cmp_info(sljit_s32 type)906{907SLJIT_UNUSED_ARG(type);908return 0;909}910911/* --------------------------------------------------------------------- */912/* Entry, exit */913/* --------------------------------------------------------------------- */914915/* Creates an index in data_transfer_insts array. */916#define LOAD_DATA 0x01917#define WORD_DATA 0x00918#define BYTE_DATA 0x02919#define HALF_DATA 0x04920#define INT_DATA 0x06921#define SIGNED_DATA 0x08922/* Separates integer and floating point registers */923#define GPR_REG 0x0f924#define DOUBLE_DATA 0x10925#define SINGLE_DATA 0x12926927#define MEM_MASK 0x1f928929#define ARG_TEST 0x00020930#define ALT_KEEP_CACHE 0x00040931#define CUMULATIVE_OP 0x00080932#define LOGICAL_OP 0x00100933#define IMM_OP 0x00200934#define MOVE_OP 0x00400935#define SRC2_IMM 0x00800936937#define UNUSED_DEST 0x01000938#define REG_DEST 0x02000939#define REG1_SOURCE 0x04000940#define REG2_SOURCE 0x08000941#define SLOW_SRC1 0x10000942#define SLOW_SRC2 0x20000943#define SLOW_DEST 0x40000944945static sljit_s32 emit_op_mem(struct sljit_compiler *compiler, sljit_s32 flags, sljit_s32 reg_ar, sljit_s32 arg, sljit_sw argw);946static sljit_s32 emit_stack_frame_release(struct sljit_compiler *compiler, sljit_s32 frame_size, sljit_ins *ins_ptr);947948#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)949#define SELECT_OP(d, w) (w)950#else951#define SELECT_OP(d, w) (!(op & SLJIT_32) ? (d) : (w))952#endif953954#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)955#include "sljitNativeMIPS_32.c"956#else957#include "sljitNativeMIPS_64.c"958#endif959960SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_enter(struct sljit_compiler *compiler,961sljit_s32 options, sljit_s32 arg_types,962sljit_s32 scratches, sljit_s32 saveds, sljit_s32 local_size)963{964sljit_s32 fscratches = ENTER_GET_FLOAT_REGS(scratches);965sljit_s32 fsaveds = ENTER_GET_FLOAT_REGS(saveds);966sljit_ins base;967sljit_s32 i, tmp, offset;968sljit_s32 arg_count, word_arg_count, float_arg_count;969sljit_s32 saved_arg_count = SLJIT_KEPT_SAVEDS_COUNT(options);970971CHECK_ERROR();972CHECK(check_sljit_emit_enter(compiler, options, arg_types, scratches, saveds, local_size));973set_emit_enter(compiler, options, arg_types, scratches, saveds, local_size);974975scratches = ENTER_GET_REGS(scratches);976saveds = ENTER_GET_REGS(saveds);977978local_size += GET_SAVED_REGISTERS_SIZE(scratches, saveds - saved_arg_count, 1);979#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)980if (fsaveds > 0 || fscratches >= SLJIT_FIRST_SAVED_FLOAT_REG) {981if ((local_size & SSIZE_OF(sw)) != 0)982local_size += SSIZE_OF(sw);983local_size += GET_SAVED_FLOAT_REGISTERS_SIZE(fscratches, fsaveds, f64);984}985986local_size = (local_size + SLJIT_LOCALS_OFFSET + 15) & ~0xf;987#else988local_size += GET_SAVED_FLOAT_REGISTERS_SIZE(fscratches, fsaveds, f64);989local_size = (local_size + SLJIT_LOCALS_OFFSET + 31) & ~0x1f;990#endif991compiler->local_size = local_size;992993offset = 0;994#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)995if (!(options & SLJIT_ENTER_REG_ARG)) {996tmp = arg_types >> SLJIT_ARG_SHIFT;997arg_count = 0;998999while (tmp) {1000offset = arg_count;1001if ((tmp & SLJIT_ARG_MASK) == SLJIT_ARG_TYPE_F64) {1002if ((arg_count & 0x1) != 0)1003arg_count++;1004arg_count++;1005}10061007arg_count++;1008tmp >>= SLJIT_ARG_SHIFT;1009}10101011compiler->args_size = (sljit_uw)arg_count << 2;1012offset = (offset >= 4) ? (offset << 2) : 0;1013}1014#endif /* SLJIT_CONFIG_MIPS_32 */10151016if (local_size + offset <= -SIMM_MIN) {1017/* Frequent case. */1018FAIL_IF(push_inst(compiler, ADDIU_W | S(SLJIT_SP) | T(SLJIT_SP) | IMM(-local_size), DR(SLJIT_SP)));1019base = S(SLJIT_SP);1020offset = local_size - SSIZE_OF(sw);1021} else {1022FAIL_IF(load_immediate(compiler, OTHER_FLAG, local_size));1023FAIL_IF(push_inst(compiler, ADDU_W | S(SLJIT_SP) | TA(0) | D(TMP_REG1), DR(TMP_REG1)));1024FAIL_IF(push_inst(compiler, SUBU_W | S(SLJIT_SP) | TA(OTHER_FLAG) | D(SLJIT_SP), DR(SLJIT_SP)));1025base = S(TMP_REG1);1026offset = -SSIZE_OF(sw);1027#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)1028local_size = 0;1029#endif1030}10311032FAIL_IF(push_inst(compiler, STORE_W | base | TA(RETURN_ADDR_REG) | IMM(offset), UNMOVABLE_INS));10331034tmp = SLJIT_S0 - saveds;1035for (i = SLJIT_S0 - saved_arg_count; i > tmp; i--) {1036offset -= SSIZE_OF(sw);1037FAIL_IF(push_inst(compiler, STORE_W | base | T(i) | IMM(offset), MOVABLE_INS));1038}10391040for (i = scratches; i >= SLJIT_FIRST_SAVED_REG; i--) {1041offset -= SSIZE_OF(sw);1042FAIL_IF(push_inst(compiler, STORE_W | base | T(i) | IMM(offset), MOVABLE_INS));1043}10441045#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)1046/* This alignment is valid because offset is not used after storing FPU regs. */1047if ((offset & SSIZE_OF(sw)) != 0)1048offset -= SSIZE_OF(sw);1049#endif10501051tmp = SLJIT_FS0 - fsaveds;1052for (i = SLJIT_FS0; i > tmp; i--) {1053offset -= SSIZE_OF(f64);1054FAIL_IF(push_inst(compiler, SDC1 | base | FT(i) | IMM(offset), MOVABLE_INS));1055}10561057for (i = fscratches; i >= SLJIT_FIRST_SAVED_FLOAT_REG; i--) {1058offset -= SSIZE_OF(f64);1059FAIL_IF(push_inst(compiler, SDC1 | base | FT(i) | IMM(offset), MOVABLE_INS));1060}10611062if (options & SLJIT_ENTER_REG_ARG)1063return SLJIT_SUCCESS;10641065arg_types >>= SLJIT_ARG_SHIFT;1066arg_count = 0;1067word_arg_count = 0;1068float_arg_count = 0;10691070#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)1071/* The first maximum two floating point arguments are passed in floating point1072registers if no integer argument precedes them. The first 16 byte data is1073passed in four integer registers, the rest is placed onto the stack.1074The floating point registers are also part of the first 16 byte data, so1075their corresponding integer registers are not used when they are present. */10761077while (arg_types) {1078switch (arg_types & SLJIT_ARG_MASK) {1079case SLJIT_ARG_TYPE_F64:1080float_arg_count++;1081if ((arg_count & 0x1) != 0)1082arg_count++;10831084if (word_arg_count == 0 && float_arg_count <= 2) {1085if (float_arg_count == 1)1086FAIL_IF(push_inst(compiler, MOV_fmt(FMT_D) | FS(TMP_FREG1) | FD(SLJIT_FR0), MOVABLE_INS));1087} else if (arg_count < 4) {1088FAIL_IF(push_inst(compiler, MTC1 | TA(4 + arg_count) | FS(float_arg_count), MOVABLE_INS));1089switch (cpu_feature_list & CPU_FEATURE_FR) {1090#if defined(SLJIT_MIPS_REV) && SLJIT_MIPS_REV >= 21091case CPU_FEATURE_FR:1092FAIL_IF(push_inst(compiler, MTHC1 | TA(5 + arg_count) | FS(float_arg_count), MOVABLE_INS));1093break;1094#endif /* SLJIT_MIPS_REV >= 2 */1095default:1096FAIL_IF(push_inst(compiler, MTC1 | TA(5 + arg_count) | FS(float_arg_count) | (1 << 11), MOVABLE_INS));1097break;1098}1099} else1100FAIL_IF(push_inst(compiler, LDC1 | base | FT(float_arg_count) | IMM(local_size + (arg_count << 2)), MOVABLE_INS));1101arg_count++;1102break;1103case SLJIT_ARG_TYPE_F32:1104float_arg_count++;11051106if (word_arg_count == 0 && float_arg_count <= 2) {1107if (float_arg_count == 1)1108FAIL_IF(push_inst(compiler, MOV_fmt(FMT_S) | FS(TMP_FREG1) | FD(SLJIT_FR0), MOVABLE_INS));1109} else if (arg_count < 4)1110FAIL_IF(push_inst(compiler, MTC1 | TA(4 + arg_count) | FS(float_arg_count), MOVABLE_INS));1111else1112FAIL_IF(push_inst(compiler, LWC1 | base | FT(float_arg_count) | IMM(local_size + (arg_count << 2)), MOVABLE_INS));1113break;1114default:1115word_arg_count++;11161117if (!(arg_types & SLJIT_ARG_TYPE_SCRATCH_REG)) {1118tmp = SLJIT_S0 - saved_arg_count;1119saved_arg_count++;1120} else if (word_arg_count != arg_count + 1 || arg_count == 0)1121tmp = word_arg_count;1122else1123break;11241125if (arg_count < 4)1126FAIL_IF(push_inst(compiler, ADDU_W | SA(4 + arg_count) | TA(0) | D(tmp), DR(tmp)));1127else1128FAIL_IF(push_inst(compiler, LW | base | T(tmp) | IMM(local_size + (arg_count << 2)), DR(tmp)));1129break;1130}1131arg_count++;1132arg_types >>= SLJIT_ARG_SHIFT;1133}11341135SLJIT_ASSERT(compiler->args_size == (sljit_uw)arg_count << 2);1136#else /* !SLJIT_CONFIG_MIPS_32 */1137while (arg_types) {1138arg_count++;1139switch (arg_types & SLJIT_ARG_MASK) {1140case SLJIT_ARG_TYPE_F64:1141float_arg_count++;1142if (arg_count != float_arg_count)1143FAIL_IF(push_inst(compiler, MOV_fmt(FMT_D) | FS(arg_count) | FD(float_arg_count), MOVABLE_INS));1144else if (arg_count == 1)1145FAIL_IF(push_inst(compiler, MOV_fmt(FMT_D) | FS(TMP_FREG1) | FD(SLJIT_FR0), MOVABLE_INS));1146break;1147case SLJIT_ARG_TYPE_F32:1148float_arg_count++;1149if (arg_count != float_arg_count)1150FAIL_IF(push_inst(compiler, MOV_fmt(FMT_S) | FS(arg_count) | FD(float_arg_count), MOVABLE_INS));1151else if (arg_count == 1)1152FAIL_IF(push_inst(compiler, MOV_fmt(FMT_S) | FS(TMP_FREG1) | FD(SLJIT_FR0), MOVABLE_INS));1153break;1154default:1155word_arg_count++;11561157if (!(arg_types & SLJIT_ARG_TYPE_SCRATCH_REG)) {1158tmp = SLJIT_S0 - saved_arg_count;1159saved_arg_count++;1160} else if (word_arg_count != arg_count || word_arg_count <= 1)1161tmp = word_arg_count;1162else1163break;11641165FAIL_IF(push_inst(compiler, ADDU_W | SA(3 + arg_count) | TA(0) | D(tmp), DR(tmp)));1166break;1167}1168arg_types >>= SLJIT_ARG_SHIFT;1169}1170#endif /* SLJIT_CONFIG_MIPS_32 */11711172return SLJIT_SUCCESS;1173}11741175SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_set_context(struct sljit_compiler *compiler,1176sljit_s32 options, sljit_s32 arg_types,1177sljit_s32 scratches, sljit_s32 saveds, sljit_s32 local_size)1178{1179sljit_s32 fscratches = ENTER_GET_FLOAT_REGS(scratches);1180sljit_s32 fsaveds = ENTER_GET_FLOAT_REGS(saveds);11811182CHECK_ERROR();1183CHECK(check_sljit_set_context(compiler, options, arg_types, scratches, saveds, local_size));1184set_emit_enter(compiler, options, arg_types, scratches, saveds, local_size);11851186scratches = ENTER_GET_REGS(scratches);1187saveds = ENTER_GET_REGS(saveds);11881189local_size += GET_SAVED_REGISTERS_SIZE(scratches, saveds - SLJIT_KEPT_SAVEDS_COUNT(options), 1);1190#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)1191if (fsaveds > 0 || fscratches >= SLJIT_FIRST_SAVED_FLOAT_REG) {1192if ((local_size & SSIZE_OF(sw)) != 0)1193local_size += SSIZE_OF(sw);1194local_size += GET_SAVED_FLOAT_REGISTERS_SIZE(fscratches, fsaveds, f64);1195}11961197compiler->local_size = (local_size + SLJIT_LOCALS_OFFSET + 15) & ~0xf;1198#else1199local_size += GET_SAVED_FLOAT_REGISTERS_SIZE(fscratches, fsaveds, f64);1200compiler->local_size = (local_size + SLJIT_LOCALS_OFFSET + 31) & ~0x1f;1201#endif1202return SLJIT_SUCCESS;1203}12041205static sljit_s32 emit_stack_frame_release(struct sljit_compiler *compiler, sljit_s32 frame_size, sljit_ins *ins_ptr)1206{1207sljit_s32 local_size, i, tmp, offset;1208sljit_s32 load_return_addr = (frame_size == 0);1209sljit_s32 scratches = compiler->scratches;1210sljit_s32 saveds = compiler->saveds;1211sljit_s32 fsaveds = compiler->fsaveds;1212sljit_s32 fscratches = compiler->fscratches;1213sljit_s32 kept_saveds_count = SLJIT_KEPT_SAVEDS_COUNT(compiler->options);12141215SLJIT_ASSERT(frame_size == 1 || (frame_size & 0xf) == 0);1216frame_size &= ~0xf;12171218local_size = compiler->local_size;12191220tmp = GET_SAVED_REGISTERS_SIZE(scratches, saveds - kept_saveds_count, 1);1221#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)1222if (fsaveds > 0 || fscratches >= SLJIT_FIRST_SAVED_FLOAT_REG) {1223if ((tmp & SSIZE_OF(sw)) != 0)1224tmp += SSIZE_OF(sw);1225tmp += GET_SAVED_FLOAT_REGISTERS_SIZE(fscratches, fsaveds, f64);1226}1227#else1228tmp += GET_SAVED_FLOAT_REGISTERS_SIZE(fscratches, fsaveds, f64);1229#endif12301231if (local_size <= SIMM_MAX) {1232if (local_size < frame_size) {1233FAIL_IF(push_inst(compiler, ADDIU_W | S(SLJIT_SP) | T(SLJIT_SP) | IMM(local_size - frame_size), DR(SLJIT_SP)));1234local_size = frame_size;1235}1236} else {1237if (tmp < frame_size)1238tmp = frame_size;12391240FAIL_IF(load_immediate(compiler, DR(TMP_REG2), local_size - tmp));1241FAIL_IF(push_inst(compiler, ADDU_W | S(SLJIT_SP) | T(TMP_REG2) | D(SLJIT_SP), DR(SLJIT_SP)));1242local_size = tmp;1243}12441245SLJIT_ASSERT(local_size >= frame_size);12461247offset = local_size - SSIZE_OF(sw);1248if (load_return_addr)1249FAIL_IF(push_inst(compiler, LOAD_W | S(SLJIT_SP) | TA(RETURN_ADDR_REG) | IMM(offset), RETURN_ADDR_REG));12501251tmp = SLJIT_S0 - saveds;1252for (i = SLJIT_S0 - kept_saveds_count; i > tmp; i--) {1253offset -= SSIZE_OF(sw);1254FAIL_IF(push_inst(compiler, LOAD_W | S(SLJIT_SP) | T(i) | IMM(offset), MOVABLE_INS));1255}12561257for (i = scratches; i >= SLJIT_FIRST_SAVED_REG; i--) {1258offset -= SSIZE_OF(sw);1259FAIL_IF(push_inst(compiler, LOAD_W | S(SLJIT_SP) | T(i) | IMM(offset), MOVABLE_INS));1260}12611262#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)1263/* This alignment is valid because offset is not used after storing FPU regs. */1264if ((offset & SSIZE_OF(sw)) != 0)1265offset -= SSIZE_OF(sw);1266#endif12671268tmp = SLJIT_FS0 - fsaveds;1269for (i = SLJIT_FS0; i > tmp; i--) {1270offset -= SSIZE_OF(f64);1271FAIL_IF(push_inst(compiler, LDC1 | S(SLJIT_SP) | FT(i) | IMM(offset), MOVABLE_INS));1272}12731274for (i = fscratches; i >= SLJIT_FIRST_SAVED_FLOAT_REG; i--) {1275offset -= SSIZE_OF(f64);1276FAIL_IF(push_inst(compiler, LDC1 | S(SLJIT_SP) | FT(i) | IMM(offset), MOVABLE_INS));1277}12781279if (local_size > frame_size)1280*ins_ptr = ADDIU_W | S(SLJIT_SP) | T(SLJIT_SP) | IMM(local_size - frame_size);1281else1282*ins_ptr = NOP;12831284return SLJIT_SUCCESS;1285}12861287SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_return_void(struct sljit_compiler *compiler)1288{1289sljit_ins ins;12901291CHECK_ERROR();1292CHECK(check_sljit_emit_return_void(compiler));12931294emit_stack_frame_release(compiler, 0, &ins);12951296FAIL_IF(push_inst(compiler, JR | SA(RETURN_ADDR_REG), UNMOVABLE_INS));1297return push_inst(compiler, ins, UNMOVABLE_INS);1298}12991300SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_return_to(struct sljit_compiler *compiler,1301sljit_s32 src, sljit_sw srcw)1302{1303sljit_ins ins;13041305CHECK_ERROR();1306CHECK(check_sljit_emit_return_to(compiler, src, srcw));13071308if (src & SLJIT_MEM) {1309ADJUST_LOCAL_OFFSET(src, srcw);1310FAIL_IF(emit_op_mem(compiler, WORD_DATA | LOAD_DATA, DR(PIC_ADDR_REG), src, srcw));1311src = PIC_ADDR_REG;1312srcw = 0;1313} else if (src >= SLJIT_FIRST_SAVED_REG && src <= (SLJIT_S0 - SLJIT_KEPT_SAVEDS_COUNT(compiler->options))) {1314FAIL_IF(push_inst(compiler, ADDU_W | S(src) | TA(0) | D(PIC_ADDR_REG), DR(PIC_ADDR_REG)));1315src = PIC_ADDR_REG;1316srcw = 0;1317}13181319FAIL_IF(emit_stack_frame_release(compiler, 1, &ins));13201321if (src != SLJIT_IMM) {1322FAIL_IF(push_inst(compiler, JR | S(src), UNMOVABLE_INS));1323return push_inst(compiler, ins, UNMOVABLE_INS);1324}13251326if (ins != NOP)1327FAIL_IF(push_inst(compiler, ins, MOVABLE_INS));13281329SLJIT_SKIP_CHECKS(compiler);1330return sljit_emit_ijump(compiler, SLJIT_JUMP, src, srcw);1331}13321333/* --------------------------------------------------------------------- */1334/* Operators */1335/* --------------------------------------------------------------------- */13361337#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)1338#define ARCH_32_64(a, b) a1339#else1340#define ARCH_32_64(a, b) b1341#endif13421343static const sljit_ins data_transfer_insts[16 + 4] = {1344/* u w s */ ARCH_32_64(HI(43) /* sw */, HI(63) /* sd */),1345/* u w l */ ARCH_32_64(HI(35) /* lw */, HI(55) /* ld */),1346/* u b s */ HI(40) /* sb */,1347/* u b l */ HI(36) /* lbu */,1348/* u h s */ HI(41) /* sh */,1349/* u h l */ HI(37) /* lhu */,1350/* u i s */ HI(43) /* sw */,1351/* u i l */ ARCH_32_64(HI(35) /* lw */, HI(39) /* lwu */),13521353/* s w s */ ARCH_32_64(HI(43) /* sw */, HI(63) /* sd */),1354/* s w l */ ARCH_32_64(HI(35) /* lw */, HI(55) /* ld */),1355/* s b s */ HI(40) /* sb */,1356/* s b l */ HI(32) /* lb */,1357/* s h s */ HI(41) /* sh */,1358/* s h l */ HI(33) /* lh */,1359/* s i s */ HI(43) /* sw */,1360/* s i l */ HI(35) /* lw */,13611362/* d s */ HI(61) /* sdc1 */,1363/* d l */ HI(53) /* ldc1 */,1364/* s s */ HI(57) /* swc1 */,1365/* s l */ HI(49) /* lwc1 */,1366};13671368#undef ARCH_32_6413691370/* reg_ar is an absoulute register! */13711372/* Can perform an operation using at most 1 instruction. */1373static sljit_s32 getput_arg_fast(struct sljit_compiler *compiler, sljit_s32 flags, sljit_s32 reg_ar, sljit_s32 arg, sljit_sw argw)1374{1375SLJIT_ASSERT(arg & SLJIT_MEM);13761377if (!(arg & OFFS_REG_MASK) && argw <= SIMM_MAX && argw >= SIMM_MIN) {1378/* Works for both absoulte and relative addresses. */1379if (SLJIT_UNLIKELY(flags & ARG_TEST))1380return 1;1381FAIL_IF(push_inst(compiler, data_transfer_insts[flags & MEM_MASK] | S(arg & REG_MASK)1382| TA(reg_ar) | IMM(argw), ((flags & MEM_MASK) <= GPR_REG && (flags & LOAD_DATA)) ? reg_ar : MOVABLE_INS));1383return -1;1384}1385return 0;1386}13871388#define TO_ARGW_HI(argw) (((argw) & ~0xffff) + (((argw) & 0x8000) ? 0x10000 : 0))13891390/* See getput_arg below.1391Note: can_cache is called only for binary operators. */1392static sljit_s32 can_cache(sljit_s32 arg, sljit_sw argw, sljit_s32 next_arg, sljit_sw next_argw)1393{1394SLJIT_ASSERT((arg & SLJIT_MEM) && (next_arg & SLJIT_MEM));13951396/* Simple operation except for updates. */1397if (arg & OFFS_REG_MASK) {1398argw &= 0x3;1399next_argw &= 0x3;1400if (argw && argw == next_argw && (arg == next_arg || (arg & OFFS_REG_MASK) == (next_arg & OFFS_REG_MASK)))1401return 1;1402return 0;1403}14041405if (arg == next_arg) {1406if (((next_argw - argw) <= SIMM_MAX && (next_argw - argw) >= SIMM_MIN)1407|| TO_ARGW_HI(argw) == TO_ARGW_HI(next_argw))1408return 1;1409return 0;1410}14111412return 0;1413}14141415/* Emit the necessary instructions. See can_cache above. */1416static 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)1417{1418sljit_s32 tmp_ar, base, delay_slot;1419sljit_sw offset, argw_hi;14201421SLJIT_ASSERT(arg & SLJIT_MEM);1422if (!(next_arg & SLJIT_MEM)) {1423next_arg = 0;1424next_argw = 0;1425}14261427/* Since tmp can be the same as base or offset registers,1428* these might be unavailable after modifying tmp. */1429if ((flags & MEM_MASK) <= GPR_REG && (flags & LOAD_DATA)) {1430tmp_ar = reg_ar;1431delay_slot = reg_ar;1432}1433else {1434tmp_ar = DR(TMP_REG1);1435delay_slot = MOVABLE_INS;1436}1437base = arg & REG_MASK;14381439if (SLJIT_UNLIKELY(arg & OFFS_REG_MASK)) {1440argw &= 0x3;14411442/* Using the cache. */1443if (argw == compiler->cache_argw) {1444if (arg == compiler->cache_arg)1445return push_inst(compiler, data_transfer_insts[flags & MEM_MASK] | S(TMP_REG3) | TA(reg_ar), delay_slot);14461447if ((SLJIT_MEM | (arg & OFFS_REG_MASK)) == compiler->cache_arg) {1448if (arg == next_arg && argw == (next_argw & 0x3)) {1449compiler->cache_arg = arg;1450compiler->cache_argw = argw;1451FAIL_IF(push_inst(compiler, ADDU_W | S(base) | T(TMP_REG3) | D(TMP_REG3), DR(TMP_REG3)));1452return push_inst(compiler, data_transfer_insts[flags & MEM_MASK] | S(TMP_REG3) | TA(reg_ar), delay_slot);1453}1454FAIL_IF(push_inst(compiler, ADDU_W | S(base) | T(TMP_REG3) | DA(tmp_ar), tmp_ar));1455return push_inst(compiler, data_transfer_insts[flags & MEM_MASK] | SA(tmp_ar) | TA(reg_ar), delay_slot);1456}1457}14581459if (SLJIT_UNLIKELY(argw)) {1460compiler->cache_arg = SLJIT_MEM | (arg & OFFS_REG_MASK);1461compiler->cache_argw = argw;1462FAIL_IF(push_inst(compiler, SLL_W | T(OFFS_REG(arg)) | D(TMP_REG3) | SH_IMM(argw), DR(TMP_REG3)));1463}14641465if (arg == next_arg && argw == (next_argw & 0x3)) {1466compiler->cache_arg = arg;1467compiler->cache_argw = argw;1468FAIL_IF(push_inst(compiler, ADDU_W | S(base) | T(!argw ? OFFS_REG(arg) : TMP_REG3) | D(TMP_REG3), DR(TMP_REG3)));1469tmp_ar = DR(TMP_REG3);1470}1471else1472FAIL_IF(push_inst(compiler, ADDU_W | S(base) | T(!argw ? OFFS_REG(arg) : TMP_REG3) | DA(tmp_ar), tmp_ar));1473return push_inst(compiler, data_transfer_insts[flags & MEM_MASK] | SA(tmp_ar) | TA(reg_ar), delay_slot);1474}14751476if (compiler->cache_arg == arg && argw - compiler->cache_argw <= SIMM_MAX && argw - compiler->cache_argw >= SIMM_MIN)1477return push_inst(compiler, data_transfer_insts[flags & MEM_MASK] | S(TMP_REG3) | TA(reg_ar) | IMM(argw - compiler->cache_argw), delay_slot);14781479if (compiler->cache_arg == SLJIT_MEM && (argw - compiler->cache_argw) <= SIMM_MAX && (argw - compiler->cache_argw) >= SIMM_MIN) {1480offset = argw - compiler->cache_argw;1481} else {1482compiler->cache_arg = SLJIT_MEM;14831484argw_hi = TO_ARGW_HI(argw);14851486if (next_arg && next_argw - argw <= SIMM_MAX && next_argw - argw >= SIMM_MIN && argw_hi != TO_ARGW_HI(next_argw)) {1487FAIL_IF(load_immediate(compiler, DR(TMP_REG3), argw));1488compiler->cache_argw = argw;1489offset = 0;1490} else {1491FAIL_IF(load_immediate(compiler, DR(TMP_REG3), argw_hi));1492compiler->cache_argw = argw_hi;1493offset = argw & 0xffff;1494argw = argw_hi;1495}1496}14971498if (!base)1499return push_inst(compiler, data_transfer_insts[flags & MEM_MASK] | S(TMP_REG3) | TA(reg_ar) | IMM(offset), delay_slot);15001501if (arg == next_arg && next_argw - argw <= SIMM_MAX && next_argw - argw >= SIMM_MIN) {1502compiler->cache_arg = arg;1503FAIL_IF(push_inst(compiler, ADDU_W | S(TMP_REG3) | T(base) | D(TMP_REG3), DR(TMP_REG3)));1504return push_inst(compiler, data_transfer_insts[flags & MEM_MASK] | S(TMP_REG3) | TA(reg_ar) | IMM(offset), delay_slot);1505}15061507FAIL_IF(push_inst(compiler, ADDU_W | S(TMP_REG3) | T(base) | DA(tmp_ar), tmp_ar));1508return push_inst(compiler, data_transfer_insts[flags & MEM_MASK] | SA(tmp_ar) | TA(reg_ar) | IMM(offset), delay_slot);1509}15101511static sljit_s32 emit_op_mem(struct sljit_compiler *compiler, sljit_s32 flags, sljit_s32 reg_ar, sljit_s32 arg, sljit_sw argw)1512{1513sljit_s32 tmp_ar, base, delay_slot;15141515if (getput_arg_fast(compiler, flags, reg_ar, arg, argw))1516return compiler->error;15171518if ((flags & MEM_MASK) <= GPR_REG && (flags & LOAD_DATA)) {1519tmp_ar = reg_ar;1520delay_slot = reg_ar;1521}1522else {1523tmp_ar = DR(TMP_REG1);1524delay_slot = MOVABLE_INS;1525}1526base = arg & REG_MASK;15271528if (SLJIT_UNLIKELY(arg & OFFS_REG_MASK)) {1529argw &= 0x3;15301531if (SLJIT_UNLIKELY(argw)) {1532FAIL_IF(push_inst(compiler, SLL_W | T(OFFS_REG(arg)) | DA(tmp_ar) | SH_IMM(argw), tmp_ar));1533FAIL_IF(push_inst(compiler, ADDU_W | SA(tmp_ar) | T(base) | DA(tmp_ar), tmp_ar));1534}1535else1536FAIL_IF(push_inst(compiler, ADDU_W | S(base) | T(OFFS_REG(arg)) | DA(tmp_ar), tmp_ar));1537return push_inst(compiler, data_transfer_insts[flags & MEM_MASK] | SA(tmp_ar) | TA(reg_ar), delay_slot);1538}15391540FAIL_IF(load_immediate(compiler, tmp_ar, TO_ARGW_HI(argw)));15411542if (base != 0)1543FAIL_IF(push_inst(compiler, ADDU_W | SA(tmp_ar) | T(base) | DA(tmp_ar), tmp_ar));15441545return push_inst(compiler, data_transfer_insts[flags & MEM_MASK] | SA(tmp_ar) | TA(reg_ar) | IMM(argw), delay_slot);1546}15471548static SLJIT_INLINE sljit_s32 emit_op_mem2(struct sljit_compiler *compiler, sljit_s32 flags, sljit_s32 reg_ar, sljit_s32 arg1, sljit_sw arg1w, sljit_s32 arg2, sljit_sw arg2w)1549{1550if (getput_arg_fast(compiler, flags, reg_ar, arg1, arg1w))1551return compiler->error;1552return getput_arg(compiler, flags, reg_ar, arg1, arg1w, arg2, arg2w);1553}15541555#define EMIT_LOGICAL(op_imm, op_reg) \1556if (flags & SRC2_IMM) { \1557if (op & SLJIT_SET_Z) \1558FAIL_IF(push_inst(compiler, op_imm | S(src1) | TA(EQUAL_FLAG) | IMM(src2), EQUAL_FLAG)); \1559if (!(flags & UNUSED_DEST)) \1560FAIL_IF(push_inst(compiler, op_imm | S(src1) | T(dst) | IMM(src2), DR(dst))); \1561} \1562else { \1563if (op & SLJIT_SET_Z) \1564FAIL_IF(push_inst(compiler, op_reg | S(src1) | T(src2) | DA(EQUAL_FLAG), EQUAL_FLAG)); \1565if (!(flags & UNUSED_DEST)) \1566FAIL_IF(push_inst(compiler, op_reg | S(src1) | T(src2) | D(dst), DR(dst))); \1567}15681569#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)15701571#define EMIT_SHIFT(dimm, dimm32, imm, dv, v) \1572op_imm = (imm); \1573op_v = (v);15741575#else /* !SLJIT_CONFIG_MIPS_32 */157615771578#define EMIT_SHIFT(dimm, dimm32, imm, dv, v) \1579op_dimm = (dimm); \1580op_dimm32 = (dimm32); \1581op_imm = (imm); \1582op_dv = (dv); \1583op_v = (v);15841585#endif /* SLJIT_CONFIG_MIPS_32 */15861587#if (!defined SLJIT_MIPS_REV || SLJIT_MIPS_REV < 1)15881589static sljit_s32 emit_clz_ctz(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 dst, sljit_sw src)1590{1591sljit_s32 is_clz = (GET_OPCODE(op) == SLJIT_CLZ);1592#if (defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64)1593sljit_ins word_size = (op & SLJIT_32) ? 32 : 64;1594#else /* !SLJIT_CONFIG_MIPS_64 */1595sljit_ins word_size = 32;1596#endif /* SLJIT_CONFIG_MIPS_64 */15971598/* The TMP_REG2 is the next value. */1599if (src != TMP_REG2)1600FAIL_IF(push_inst(compiler, SELECT_OP(DADDU, ADDU) | S(src) | TA(0) | D(TMP_REG2), DR(TMP_REG2)));16011602FAIL_IF(push_inst(compiler, BEQ | S(TMP_REG2) | TA(0) | IMM(is_clz ? 13 : 14), UNMOVABLE_INS));1603/* The OTHER_FLAG is the counter. Delay slot. */1604FAIL_IF(push_inst(compiler, SELECT_OP(DADDIU, ADDIU) | SA(0) | TA(OTHER_FLAG) | IMM(word_size), OTHER_FLAG));16051606if (!is_clz) {1607FAIL_IF(push_inst(compiler, ANDI | S(TMP_REG2) | T(TMP_REG1) | IMM(1), DR(TMP_REG1)));1608FAIL_IF(push_inst(compiler, BNE | S(TMP_REG1) | TA(0) | IMM(11), UNMOVABLE_INS));1609} else1610FAIL_IF(push_inst(compiler, BLTZ | S(TMP_REG2) | TA(0) | IMM(11), UNMOVABLE_INS));16111612/* Delay slot. */1613FAIL_IF(push_inst(compiler, SELECT_OP(DADDIU, ADDIU) | SA(0) | TA(OTHER_FLAG) | IMM(0), OTHER_FLAG));16141615/* The TMP_REG1 is the next shift. */1616FAIL_IF(push_inst(compiler, SELECT_OP(DADDIU, ADDIU) | SA(0) | T(TMP_REG1) | IMM(word_size), DR(TMP_REG1)));16171618FAIL_IF(push_inst(compiler, SELECT_OP(DADDU, ADDU) | S(TMP_REG2) | TA(0) | DA(EQUAL_FLAG), EQUAL_FLAG));1619FAIL_IF(push_inst(compiler, SELECT_OP(DSRL, SRL) | T(TMP_REG1) | D(TMP_REG1) | SH_IMM(1), DR(TMP_REG1)));16201621FAIL_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)));1622FAIL_IF(push_inst(compiler, BNE | S(TMP_REG2) | TA(0) | IMM(-4), UNMOVABLE_INS));1623/* Delay slot. */1624FAIL_IF(push_inst(compiler, NOP, UNMOVABLE_INS));16251626FAIL_IF(push_inst(compiler, SELECT_OP(DADDIU, ADDIU) | S(TMP_REG1) | T(TMP_REG2) | IMM(-1), DR(TMP_REG2)));1627FAIL_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)));16281629FAIL_IF(push_inst(compiler, BEQ | S(TMP_REG2) | TA(0) | IMM(-7), UNMOVABLE_INS));1630/* Delay slot. */1631FAIL_IF(push_inst(compiler, OR | SA(OTHER_FLAG) | T(TMP_REG1) | DA(OTHER_FLAG), OTHER_FLAG));16321633return push_inst(compiler, SELECT_OP(DADDU, ADDU) | SA(OTHER_FLAG) | TA(0) | D(dst), DR(dst));1634}16351636#endif /* SLJIT_MIPS_REV < 1 */16371638static sljit_s32 emit_rev(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 dst, sljit_sw src)1639{1640#if defined(SLJIT_CONFIG_MIPS_64) && SLJIT_CONFIG_MIPS_641641int is_32 = (op & SLJIT_32);1642#endif /* SLJIT_CONFIG_MIPS_64 */16431644op = GET_OPCODE(op);1645#if defined(SLJIT_MIPS_REV) && SLJIT_MIPS_REV >= 21646#if defined(SLJIT_CONFIG_MIPS_64) && SLJIT_CONFIG_MIPS_641647if (!is_32 && (op == SLJIT_REV)) {1648FAIL_IF(push_inst(compiler, DSBH | T(src) | D(dst), DR(dst)));1649return push_inst(compiler, DSHD | T(dst) | D(dst), DR(dst));1650}1651if (op != SLJIT_REV && src != TMP_REG2) {1652FAIL_IF(push_inst(compiler, SLL | T(src) | D(TMP_REG1), DR(TMP_REG1)));1653src = TMP_REG1;1654}1655#endif /* SLJIT_CONFIG_MIPS_64 */1656FAIL_IF(push_inst(compiler, WSBH | T(src) | D(dst), DR(dst)));1657FAIL_IF(push_inst(compiler, ROTR | T(dst) | D(dst) | SH_IMM(16), DR(dst)));1658#if defined(SLJIT_CONFIG_MIPS_64) && SLJIT_CONFIG_MIPS_641659if (op == SLJIT_REV_U32 && dst != TMP_REG2 && dst != TMP_REG3)1660FAIL_IF(push_inst(compiler, DINSU | T(dst) | SA(0) | (31 << 11), DR(dst)));1661#endif /* SLJIT_CONFIG_MIPS_64 */1662#else /* SLJIT_MIPS_REV < 2 */1663#if (defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64)1664if (!is_32) {1665FAIL_IF(push_inst(compiler, DSRL32 | T(src) | D(TMP_REG1) | SH_IMM(0), DR(TMP_REG1)));1666FAIL_IF(push_inst(compiler, ORI | SA(0) | TA(OTHER_FLAG) | 0xffff, OTHER_FLAG));1667FAIL_IF(push_inst(compiler, DSLL32 | T(src) | D(dst) | SH_IMM(0), DR(dst)));1668FAIL_IF(push_inst(compiler, DSLL32 | TA(OTHER_FLAG) | DA(OTHER_FLAG) | SH_IMM(0), OTHER_FLAG));1669FAIL_IF(push_inst(compiler, OR | S(dst) | T(TMP_REG1) | D(dst), DR(dst)));16701671FAIL_IF(push_inst(compiler, DSRL | T(dst) | D(TMP_REG1) | SH_IMM(16), DR(TMP_REG1)));1672FAIL_IF(push_inst(compiler, ORI | SA(OTHER_FLAG) | TA(OTHER_FLAG) | 0xffff, OTHER_FLAG));1673FAIL_IF(push_inst(compiler, AND | S(dst) | TA(OTHER_FLAG) | D(dst), DR(dst)));1674FAIL_IF(push_inst(compiler, AND | S(TMP_REG1) | TA(OTHER_FLAG) | D(TMP_REG1), DR(TMP_REG1)));1675FAIL_IF(push_inst(compiler, DSLL | TA(OTHER_FLAG) | DA(EQUAL_FLAG) | SH_IMM(8), EQUAL_FLAG));1676FAIL_IF(push_inst(compiler, DSLL | T(dst) | D(dst) | SH_IMM(16), DR(dst)));1677FAIL_IF(push_inst(compiler, XOR | SA(OTHER_FLAG) | TA(EQUAL_FLAG) | DA(OTHER_FLAG), OTHER_FLAG));1678FAIL_IF(push_inst(compiler, OR | S(dst) | T(TMP_REG1) | D(dst), DR(dst)));16791680FAIL_IF(push_inst(compiler, DSRL | T(dst) | D(TMP_REG1) | SH_IMM(8), DR(TMP_REG1)));1681FAIL_IF(push_inst(compiler, AND | S(dst) | TA(OTHER_FLAG) | D(dst), DR(dst)));1682FAIL_IF(push_inst(compiler, AND | S(TMP_REG1) | TA(OTHER_FLAG) | D(TMP_REG1), DR(TMP_REG1)));1683FAIL_IF(push_inst(compiler, DSLL | T(dst) | D(dst) | SH_IMM(8), DR(dst)));1684return push_inst(compiler, OR | S(dst) | T(TMP_REG1) | D(dst), DR(dst));1685}16861687if (op != SLJIT_REV && src != TMP_REG2) {1688FAIL_IF(push_inst(compiler, SLL | T(src) | D(TMP_REG2) | SH_IMM(0), DR(TMP_REG2)));1689src = TMP_REG2;1690}1691#endif /* SLJIT_CONFIG_MIPS_64 */16921693FAIL_IF(push_inst(compiler, SRL | T(src) | D(TMP_REG1) | SH_IMM(16), DR(TMP_REG1)));1694FAIL_IF(push_inst(compiler, LUI | TA(OTHER_FLAG) | 0xff, OTHER_FLAG));1695FAIL_IF(push_inst(compiler, SLL | T(src) | D(dst) | SH_IMM(16), DR(dst)));1696FAIL_IF(push_inst(compiler, ORI | SA(OTHER_FLAG) | TA(OTHER_FLAG) | 0xff, OTHER_FLAG));1697FAIL_IF(push_inst(compiler, OR | S(dst) | T(TMP_REG1) | D(dst), DR(dst)));16981699FAIL_IF(push_inst(compiler, SRL | T(dst) | D(TMP_REG1) | SH_IMM(8), DR(TMP_REG1)));1700FAIL_IF(push_inst(compiler, AND | S(dst) | TA(OTHER_FLAG) | D(dst), DR(dst)));1701FAIL_IF(push_inst(compiler, AND | S(TMP_REG1) | TA(OTHER_FLAG) | D(TMP_REG1), DR(TMP_REG1)));1702FAIL_IF(push_inst(compiler, SLL | T(dst) | D(dst) | SH_IMM(8), DR(dst)));1703FAIL_IF(push_inst(compiler, OR | S(dst) | T(TMP_REG1) | D(dst), DR(dst)));17041705#if (defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64)1706if (op == SLJIT_REV_U32 && dst != TMP_REG2 && dst != TMP_REG3) {1707FAIL_IF(push_inst(compiler, DSLL32 | T(dst) | D(dst) | SH_IMM(0), DR(dst)));1708FAIL_IF(push_inst(compiler, DSRL32 | T(dst) | D(dst) | SH_IMM(0), DR(dst)));1709}1710#endif /* SLJIT_CONFIG_MIPS_64 */1711#endif /* SLJIT_MIPR_REV >= 2 */1712return SLJIT_SUCCESS;1713}17141715static sljit_s32 emit_rev16(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 dst, sljit_sw src)1716{1717#if defined(SLJIT_MIPS_REV) && SLJIT_MIPS_REV >= 21718#if defined(SLJIT_CONFIG_MIPS_32) && SLJIT_CONFIG_MIPS_321719FAIL_IF(push_inst(compiler, WSBH | T(src) | D(dst), DR(dst)));1720#else /* !SLJIT_CONFIG_MIPS_32 */1721FAIL_IF(push_inst(compiler, DSBH | T(src) | D(dst), DR(dst)));1722#endif /* SLJIT_CONFIG_MIPS_32 */1723if (GET_OPCODE(op) == SLJIT_REV_U16)1724return push_inst(compiler, ANDI | S(dst) | T(dst) | 0xffff, DR(dst));1725else1726return push_inst(compiler, SEH | T(dst) | D(dst), DR(dst));1727#else /* SLJIT_MIPS_REV < 2 */1728FAIL_IF(push_inst(compiler, SELECT_OP(DSRL, SRL) | T(src) | D(TMP_REG1) | SH_IMM(8), DR(TMP_REG1)));1729FAIL_IF(push_inst(compiler, SELECT_OP(DSLL32, SLL) | T(src) | D(dst) | SH_IMM(24), DR(dst)));1730FAIL_IF(push_inst(compiler, ANDI | S(TMP_REG1) | T(TMP_REG1) | 0xff, DR(TMP_REG1)));1731FAIL_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)));1732return push_inst(compiler, OR | S(dst) | T(TMP_REG1) | D(dst), DR(dst));1733#endif /* SLJIT_MIPS_REV >= 2 */1734}17351736static SLJIT_INLINE sljit_s32 emit_single_op(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 flags,1737sljit_s32 dst, sljit_s32 src1, sljit_sw src2)1738{1739sljit_s32 is_overflow, is_carry, carry_src_ar, is_handled, reg;1740sljit_ins op_imm, op_v;1741#if (defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64)1742sljit_ins ins, op_dimm, op_dimm32, op_dv;1743#endif17441745switch (GET_OPCODE(op)) {1746case SLJIT_MOV:1747SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & SRC2_IMM));1748if (dst != src2)1749return push_inst(compiler, SELECT_OP(DADDU, ADDU) | S(src2) | TA(0) | D(dst), DR(dst));1750return SLJIT_SUCCESS;17511752case SLJIT_MOV_U8:1753SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & SRC2_IMM));1754if ((flags & (REG_DEST | REG2_SOURCE)) == (REG_DEST | REG2_SOURCE))1755return push_inst(compiler, ANDI | S(src2) | T(dst) | IMM(0xff), DR(dst));1756SLJIT_ASSERT(dst == src2);1757return SLJIT_SUCCESS;17581759case SLJIT_MOV_S8:1760SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & SRC2_IMM));1761if ((flags & (REG_DEST | REG2_SOURCE)) == (REG_DEST | REG2_SOURCE)) {1762#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)1763#if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 2)1764return push_inst(compiler, SEB | T(src2) | D(dst), DR(dst));1765#else /* SLJIT_MIPS_REV < 2 */1766FAIL_IF(push_inst(compiler, SLL | T(src2) | D(dst) | SH_IMM(24), DR(dst)));1767return push_inst(compiler, SRA | T(dst) | D(dst) | SH_IMM(24), DR(dst));1768#endif /* SLJIT_MIPS_REV >= 2 */1769#else /* !SLJIT_CONFIG_MIPS_32 */1770#if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 2)1771if (op & SLJIT_32)1772return push_inst(compiler, SEB | T(src2) | D(dst), DR(dst));1773#endif /* SLJIT_MIPS_REV >= 2 */1774FAIL_IF(push_inst(compiler, DSLL32 | T(src2) | D(dst) | SH_IMM(24), DR(dst)));1775return push_inst(compiler, DSRA32 | T(dst) | D(dst) | SH_IMM(24), DR(dst));1776#endif /* SLJIT_CONFIG_MIPS_32 */1777}1778SLJIT_ASSERT(dst == src2);1779return SLJIT_SUCCESS;17801781case SLJIT_MOV_U16:1782SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & SRC2_IMM));1783if ((flags & (REG_DEST | REG2_SOURCE)) == (REG_DEST | REG2_SOURCE))1784return push_inst(compiler, ANDI | S(src2) | T(dst) | IMM(0xffff), DR(dst));1785SLJIT_ASSERT(dst == src2);1786return SLJIT_SUCCESS;17871788case SLJIT_MOV_S16:1789SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & SRC2_IMM));1790if ((flags & (REG_DEST | REG2_SOURCE)) == (REG_DEST | REG2_SOURCE)) {1791#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)1792#if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 2)1793return push_inst(compiler, SEH | T(src2) | D(dst), DR(dst));1794#else /* SLJIT_MIPS_REV < 2 */1795FAIL_IF(push_inst(compiler, SLL | T(src2) | D(dst) | SH_IMM(16), DR(dst)));1796return push_inst(compiler, SRA | T(dst) | D(dst) | SH_IMM(16), DR(dst));1797#endif /* SLJIT_MIPS_REV >= 2 */1798#else /* !SLJIT_CONFIG_MIPS_32 */1799#if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 2)1800if (op & SLJIT_32)1801return push_inst(compiler, SEH | T(src2) | D(dst), DR(dst));1802#endif /* SLJIT_MIPS_REV >= 2 */1803FAIL_IF(push_inst(compiler, DSLL32 | T(src2) | D(dst) | SH_IMM(16), DR(dst)));1804return push_inst(compiler, DSRA32 | T(dst) | D(dst) | SH_IMM(16), DR(dst));1805#endif /* SLJIT_CONFIG_MIPS_32 */1806}1807SLJIT_ASSERT(dst == src2);1808return SLJIT_SUCCESS;18091810#if (defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64)1811case SLJIT_MOV_U32:1812SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & SRC2_IMM) && !(op & SLJIT_32));1813if ((flags & (REG_DEST | REG2_SOURCE)) == (REG_DEST | REG2_SOURCE)) {1814#if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 2)1815if (dst == src2)1816return push_inst(compiler, DINSU | T(src2) | SA(0) | (31 << 11), DR(dst));1817#endif /* SLJIT_MIPS_REV >= 2 */1818FAIL_IF(push_inst(compiler, DSLL32 | T(src2) | D(dst) | SH_IMM(0), DR(dst)));1819return push_inst(compiler, DSRL32 | T(dst) | D(dst) | SH_IMM(0), DR(dst));1820}1821SLJIT_ASSERT(dst == src2);1822return SLJIT_SUCCESS;18231824case SLJIT_MOV_S32:1825SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & SRC2_IMM) && !(op & SLJIT_32));1826if ((flags & (REG_DEST | REG2_SOURCE)) == (REG_DEST | REG2_SOURCE)) {1827return push_inst(compiler, SLL | T(src2) | D(dst) | SH_IMM(0), DR(dst));1828}1829SLJIT_ASSERT(dst == src2);1830return SLJIT_SUCCESS;1831#endif /* SLJIT_CONFIG_MIPS_64 */18321833#if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 1)1834case SLJIT_CLZ:1835SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & SRC2_IMM));1836#if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 6)1837return push_inst(compiler, SELECT_OP(DCLZ, CLZ) | S(src2) | D(dst), DR(dst));1838#else /* SLJIT_MIPS_REV < 6 */1839return push_inst(compiler, SELECT_OP(DCLZ, CLZ) | S(src2) | T(dst) | D(dst), DR(dst));1840#endif /* SLJIT_MIPS_REV >= 6 */1841case SLJIT_CTZ:1842SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & SRC2_IMM));1843FAIL_IF(push_inst(compiler, SELECT_OP(DSUBU, SUBU) | SA(0) | T(src2) | D(TMP_REG1), DR(TMP_REG1)));1844FAIL_IF(push_inst(compiler, AND | S(src2) | T(TMP_REG1) | D(dst), DR(dst)));1845#if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 6)1846FAIL_IF(push_inst(compiler, SELECT_OP(DCLZ, CLZ) | S(dst) | D(dst), DR(dst)));1847#else /* SLJIT_MIPS_REV < 6 */1848FAIL_IF(push_inst(compiler, SELECT_OP(DCLZ, CLZ) | S(dst) | T(dst) | D(dst), DR(dst)));1849#endif /* SLJIT_MIPS_REV >= 6 */1850FAIL_IF(push_inst(compiler, SELECT_OP(DADDIU, ADDIU) | S(dst) | T(TMP_REG1) | IMM(SELECT_OP(-64, -32)), DR(TMP_REG1)));1851FAIL_IF(push_inst(compiler, SELECT_OP(DSRL32, SRL) | T(TMP_REG1) | D(TMP_REG1) | SH_IMM(SELECT_OP(26, 27)), DR(TMP_REG1)));1852return push_inst(compiler, XOR | S(dst) | T(TMP_REG1) | D(dst), DR(dst));1853#else /* SLJIT_MIPS_REV < 1 */1854case SLJIT_CLZ:1855case SLJIT_CTZ:1856SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & SRC2_IMM));1857return emit_clz_ctz(compiler, op, dst, src2);1858#endif /* SLJIT_MIPS_REV >= 1 */18591860case SLJIT_REV:1861case SLJIT_REV_U32:1862case SLJIT_REV_S32:1863SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & SRC2_IMM) && src2 != TMP_REG1 && dst != TMP_REG1);1864return emit_rev(compiler, op, dst, src2);18651866case SLJIT_REV_U16:1867case SLJIT_REV_S16:1868SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & SRC2_IMM));1869return emit_rev16(compiler, op, dst, src2);18701871case SLJIT_ADD:1872/* Overflow computation (both add and sub): overflow = src1_sign ^ src2_sign ^ result_sign ^ carry_flag */1873is_overflow = GET_FLAG_TYPE(op) == SLJIT_OVERFLOW;1874carry_src_ar = GET_FLAG_TYPE(op) == SLJIT_CARRY;18751876if (flags & SRC2_IMM) {1877if (is_overflow) {1878if (src2 >= 0)1879FAIL_IF(push_inst(compiler, OR | S(src1) | T(src1) | DA(EQUAL_FLAG), EQUAL_FLAG));1880else1881FAIL_IF(push_inst(compiler, NOR | S(src1) | T(src1) | DA(EQUAL_FLAG), EQUAL_FLAG));1882}1883else if (op & SLJIT_SET_Z)1884FAIL_IF(push_inst(compiler, SELECT_OP(DADDIU, ADDIU) | S(src1) | TA(EQUAL_FLAG) | IMM(src2), EQUAL_FLAG));18851886/* Only the zero flag is needed. */1887if (!(flags & UNUSED_DEST) || (op & VARIABLE_FLAG_MASK))1888FAIL_IF(push_inst(compiler, SELECT_OP(DADDIU, ADDIU) | S(src1) | T(dst) | IMM(src2), DR(dst)));1889}1890else {1891if (is_overflow)1892FAIL_IF(push_inst(compiler, XOR | S(src1) | T(src2) | DA(EQUAL_FLAG), EQUAL_FLAG));1893else if (op & SLJIT_SET_Z)1894FAIL_IF(push_inst(compiler, SELECT_OP(DADDU, ADDU) | S(src1) | T(src2) | DA(EQUAL_FLAG), EQUAL_FLAG));18951896if (is_overflow || carry_src_ar != 0) {1897if (src1 != dst)1898carry_src_ar = DR(src1);1899else if (src2 != dst)1900carry_src_ar = DR(src2);1901else {1902FAIL_IF(push_inst(compiler, SELECT_OP(DADDU, ADDU) | S(src1) | TA(0) | DA(OTHER_FLAG), OTHER_FLAG));1903carry_src_ar = OTHER_FLAG;1904}1905}19061907/* Only the zero flag is needed. */1908if (!(flags & UNUSED_DEST) || (op & VARIABLE_FLAG_MASK))1909FAIL_IF(push_inst(compiler, SELECT_OP(DADDU, ADDU) | S(src1) | T(src2) | D(dst), DR(dst)));1910}19111912/* Carry is zero if a + b >= a or a + b >= b, otherwise it is 1. */1913if (is_overflow || carry_src_ar != 0) {1914if (flags & SRC2_IMM)1915FAIL_IF(push_inst(compiler, SLTIU | S(dst) | TA(OTHER_FLAG) | IMM(src2), OTHER_FLAG));1916else1917FAIL_IF(push_inst(compiler, SLTU | S(dst) | TA(carry_src_ar) | DA(OTHER_FLAG), OTHER_FLAG));1918}19191920if (!is_overflow)1921return SLJIT_SUCCESS;19221923FAIL_IF(push_inst(compiler, XOR | S(dst) | TA(EQUAL_FLAG) | D(TMP_REG1), DR(TMP_REG1)));1924if (op & SLJIT_SET_Z)1925FAIL_IF(push_inst(compiler, SELECT_OP(DADDU, ADDU) | S(dst) | TA(0) | DA(EQUAL_FLAG), EQUAL_FLAG));1926FAIL_IF(push_inst(compiler, SELECT_OP(DSRL32, SRL) | T(TMP_REG1) | D(TMP_REG1) | SH_IMM(31), DR(TMP_REG1)));1927return push_inst(compiler, XOR | S(TMP_REG1) | TA(OTHER_FLAG) | DA(OTHER_FLAG), OTHER_FLAG);19281929case SLJIT_ADDC:1930carry_src_ar = GET_FLAG_TYPE(op) == SLJIT_CARRY;19311932if (flags & SRC2_IMM) {1933FAIL_IF(push_inst(compiler, SELECT_OP(DADDIU, ADDIU) | S(src1) | T(dst) | IMM(src2), DR(dst)));1934} else {1935if (carry_src_ar != 0) {1936if (src1 != dst)1937carry_src_ar = DR(src1);1938else if (src2 != dst)1939carry_src_ar = DR(src2);1940else {1941FAIL_IF(push_inst(compiler, SELECT_OP(DADDU, ADDU) | S(src1) | TA(0) | DA(EQUAL_FLAG), EQUAL_FLAG));1942carry_src_ar = EQUAL_FLAG;1943}1944}19451946FAIL_IF(push_inst(compiler, SELECT_OP(DADDU, ADDU) | S(src1) | T(src2) | D(dst), DR(dst)));1947}19481949/* Carry is zero if a + b >= a or a + b >= b, otherwise it is 1. */1950if (carry_src_ar != 0) {1951if (flags & SRC2_IMM)1952FAIL_IF(push_inst(compiler, SLTIU | S(dst) | TA(EQUAL_FLAG) | IMM(src2), EQUAL_FLAG));1953else1954FAIL_IF(push_inst(compiler, SLTU | S(dst) | TA(carry_src_ar) | DA(EQUAL_FLAG), EQUAL_FLAG));1955}19561957FAIL_IF(push_inst(compiler, SELECT_OP(DADDU, ADDU) | S(dst) | TA(OTHER_FLAG) | D(dst), DR(dst)));19581959if (carry_src_ar == 0)1960return SLJIT_SUCCESS;19611962/* Set ULESS_FLAG (dst == 0) && (OTHER_FLAG == 1). */1963FAIL_IF(push_inst(compiler, SLTU | S(dst) | TA(OTHER_FLAG) | DA(OTHER_FLAG), OTHER_FLAG));1964/* Set carry flag. */1965return push_inst(compiler, OR | SA(OTHER_FLAG) | TA(EQUAL_FLAG) | DA(OTHER_FLAG), OTHER_FLAG);19661967case SLJIT_SUB:1968if ((flags & SRC2_IMM) && src2 == SIMM_MIN) {1969FAIL_IF(push_inst(compiler, ADDIU | SA(0) | T(TMP_REG2) | IMM(src2), DR(TMP_REG2)));1970src2 = TMP_REG2;1971flags &= ~SRC2_IMM;1972}19731974is_handled = 0;19751976if (flags & SRC2_IMM) {1977if (GET_FLAG_TYPE(op) == SLJIT_LESS) {1978FAIL_IF(push_inst(compiler, SLTIU | S(src1) | TA(OTHER_FLAG) | IMM(src2), OTHER_FLAG));1979is_handled = 1;1980}1981else if (GET_FLAG_TYPE(op) == SLJIT_SIG_LESS) {1982FAIL_IF(push_inst(compiler, SLTI | S(src1) | TA(OTHER_FLAG) | IMM(src2), OTHER_FLAG));1983is_handled = 1;1984}1985}19861987if (!is_handled && GET_FLAG_TYPE(op) >= SLJIT_LESS && GET_FLAG_TYPE(op) <= SLJIT_SIG_LESS_EQUAL) {1988is_handled = 1;19891990if (flags & SRC2_IMM) {1991reg = (src1 == TMP_REG1) ? TMP_REG2 : TMP_REG1;1992FAIL_IF(push_inst(compiler, ADDIU | SA(0) | T(reg) | IMM(src2), DR(reg)));1993src2 = reg;1994flags &= ~SRC2_IMM;1995}19961997switch (GET_FLAG_TYPE(op)) {1998case SLJIT_LESS:1999FAIL_IF(push_inst(compiler, SLTU | S(src1) | T(src2) | DA(OTHER_FLAG), OTHER_FLAG));2000break;2001case SLJIT_GREATER:2002FAIL_IF(push_inst(compiler, SLTU | S(src2) | T(src1) | DA(OTHER_FLAG), OTHER_FLAG));2003break;2004case SLJIT_SIG_LESS:2005FAIL_IF(push_inst(compiler, SLT | S(src1) | T(src2) | DA(OTHER_FLAG), OTHER_FLAG));2006break;2007case SLJIT_SIG_GREATER:2008FAIL_IF(push_inst(compiler, SLT | S(src2) | T(src1) | DA(OTHER_FLAG), OTHER_FLAG));2009break;2010}2011}20122013if (is_handled) {2014if (flags & SRC2_IMM) {2015if (op & SLJIT_SET_Z)2016FAIL_IF(push_inst(compiler, SELECT_OP(DADDIU, ADDIU) | S(src1) | TA(EQUAL_FLAG) | IMM(-src2), EQUAL_FLAG));2017if (!(flags & UNUSED_DEST))2018return push_inst(compiler, SELECT_OP(DADDIU, ADDIU) | S(src1) | T(dst) | IMM(-src2), DR(dst));2019}2020else {2021if (op & SLJIT_SET_Z)2022FAIL_IF(push_inst(compiler, SELECT_OP(DSUBU, SUBU) | S(src1) | T(src2) | DA(EQUAL_FLAG), EQUAL_FLAG));2023if (!(flags & UNUSED_DEST))2024return push_inst(compiler, SELECT_OP(DSUBU, SUBU) | S(src1) | T(src2) | D(dst), DR(dst));2025}2026return SLJIT_SUCCESS;2027}20282029is_overflow = GET_FLAG_TYPE(op) == SLJIT_OVERFLOW;2030is_carry = GET_FLAG_TYPE(op) == SLJIT_CARRY;20312032if (flags & SRC2_IMM) {2033if (is_overflow) {2034if (src2 >= 0)2035FAIL_IF(push_inst(compiler, OR | S(src1) | T(src1) | DA(EQUAL_FLAG), EQUAL_FLAG));2036else2037FAIL_IF(push_inst(compiler, NOR | S(src1) | T(src1) | DA(EQUAL_FLAG), EQUAL_FLAG));2038}2039else if (op & SLJIT_SET_Z)2040FAIL_IF(push_inst(compiler, SELECT_OP(DADDIU, ADDIU) | S(src1) | TA(EQUAL_FLAG) | IMM(-src2), EQUAL_FLAG));20412042if (is_overflow || is_carry)2043FAIL_IF(push_inst(compiler, SLTIU | S(src1) | TA(OTHER_FLAG) | IMM(src2), OTHER_FLAG));20442045/* Only the zero flag is needed. */2046if (!(flags & UNUSED_DEST) || (op & VARIABLE_FLAG_MASK))2047FAIL_IF(push_inst(compiler, SELECT_OP(DADDIU, ADDIU) | S(src1) | T(dst) | IMM(-src2), DR(dst)));2048}2049else {2050if (is_overflow)2051FAIL_IF(push_inst(compiler, XOR | S(src1) | T(src2) | DA(EQUAL_FLAG), EQUAL_FLAG));2052else if (op & SLJIT_SET_Z)2053FAIL_IF(push_inst(compiler, SELECT_OP(DSUBU, SUBU) | S(src1) | T(src2) | DA(EQUAL_FLAG), EQUAL_FLAG));20542055if (is_overflow || is_carry)2056FAIL_IF(push_inst(compiler, SLTU | S(src1) | T(src2) | DA(OTHER_FLAG), OTHER_FLAG));20572058/* Only the zero flag is needed. */2059if (!(flags & UNUSED_DEST) || (op & VARIABLE_FLAG_MASK))2060FAIL_IF(push_inst(compiler, SELECT_OP(DSUBU, SUBU) | S(src1) | T(src2) | D(dst), DR(dst)));2061}20622063if (!is_overflow)2064return SLJIT_SUCCESS;20652066FAIL_IF(push_inst(compiler, XOR | S(dst) | TA(EQUAL_FLAG) | D(TMP_REG1), DR(TMP_REG1)));2067if (op & SLJIT_SET_Z)2068FAIL_IF(push_inst(compiler, SELECT_OP(DADDU, ADDU) | S(dst) | TA(0) | DA(EQUAL_FLAG), EQUAL_FLAG));2069FAIL_IF(push_inst(compiler, SELECT_OP(DSRL32, SRL) | T(TMP_REG1) | D(TMP_REG1) | SH_IMM(31), DR(TMP_REG1)));2070return push_inst(compiler, XOR | S(TMP_REG1) | TA(OTHER_FLAG) | DA(OTHER_FLAG), OTHER_FLAG);20712072case SLJIT_SUBC:2073if ((flags & SRC2_IMM) && src2 == SIMM_MIN) {2074FAIL_IF(push_inst(compiler, ADDIU | SA(0) | T(TMP_REG2) | IMM(src2), DR(TMP_REG2)));2075src2 = TMP_REG2;2076flags &= ~SRC2_IMM;2077}20782079is_carry = GET_FLAG_TYPE(op) == SLJIT_CARRY;20802081if (flags & SRC2_IMM) {2082if (is_carry)2083FAIL_IF(push_inst(compiler, SLTIU | S(src1) | TA(EQUAL_FLAG) | IMM(src2), EQUAL_FLAG));20842085FAIL_IF(push_inst(compiler, SELECT_OP(DADDIU, ADDIU) | S(src1) | T(dst) | IMM(-src2), DR(dst)));2086}2087else {2088if (is_carry)2089FAIL_IF(push_inst(compiler, SLTU | S(src1) | T(src2) | DA(EQUAL_FLAG), EQUAL_FLAG));20902091FAIL_IF(push_inst(compiler, SELECT_OP(DSUBU, SUBU) | S(src1) | T(src2) | D(dst), DR(dst)));2092}20932094if (is_carry)2095FAIL_IF(push_inst(compiler, SLTU | S(dst) | TA(OTHER_FLAG) | D(TMP_REG1), DR(TMP_REG1)));20962097FAIL_IF(push_inst(compiler, SELECT_OP(DSUBU, SUBU) | S(dst) | TA(OTHER_FLAG) | D(dst), DR(dst)));20982099if (!is_carry)2100return SLJIT_SUCCESS;21012102return push_inst(compiler, OR | SA(EQUAL_FLAG) | T(TMP_REG1) | DA(OTHER_FLAG), OTHER_FLAG);21032104case SLJIT_MUL:2105SLJIT_ASSERT(!(flags & SRC2_IMM));21062107if (GET_FLAG_TYPE(op) != SLJIT_OVERFLOW) {2108#if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 6)2109return push_inst(compiler, SELECT_OP(DMUL, MUL) | S(src1) | T(src2) | D(dst), DR(dst));2110#elif (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 1)2111#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)2112return push_inst(compiler, MUL | S(src1) | T(src2) | D(dst), DR(dst));2113#else /* !SLJIT_CONFIG_MIPS_32 */2114if (op & SLJIT_32)2115return push_inst(compiler, MUL | S(src1) | T(src2) | D(dst), DR(dst));2116FAIL_IF(push_inst(compiler, DMULT | S(src1) | T(src2), MOVABLE_INS));2117return push_inst(compiler, MFLO | D(dst), DR(dst));2118#endif /* SLJIT_CONFIG_MIPS_32 */2119#else /* SLJIT_MIPS_REV < 1 */2120FAIL_IF(push_inst(compiler, SELECT_OP(DMULT, MULT) | S(src1) | T(src2), MOVABLE_INS));2121return push_inst(compiler, MFLO | D(dst), DR(dst));2122#endif /* SLJIT_MIPS_REV >= 6 */2123}21242125#if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 6)2126FAIL_IF(push_inst(compiler, SELECT_OP(DMUL, MUL) | S(src1) | T(src2) | D(dst), DR(dst)));2127FAIL_IF(push_inst(compiler, SELECT_OP(DMUH, MUH) | S(src1) | T(src2) | DA(EQUAL_FLAG), EQUAL_FLAG));2128#else /* SLJIT_MIPS_REV < 6 */2129FAIL_IF(push_inst(compiler, SELECT_OP(DMULT, MULT) | S(src1) | T(src2), MOVABLE_INS));2130FAIL_IF(push_inst(compiler, MFHI | DA(EQUAL_FLAG), EQUAL_FLAG));2131FAIL_IF(push_inst(compiler, MFLO | D(dst), DR(dst)));2132#endif /* SLJIT_MIPS_REV >= 6 */2133FAIL_IF(push_inst(compiler, SELECT_OP(DSRA32, SRA) | T(dst) | DA(OTHER_FLAG) | SH_IMM(31), OTHER_FLAG));2134return push_inst(compiler, SELECT_OP(DSUBU, SUBU) | SA(EQUAL_FLAG) | TA(OTHER_FLAG) | DA(OTHER_FLAG), OTHER_FLAG);21352136case SLJIT_AND:2137EMIT_LOGICAL(ANDI, AND);2138return SLJIT_SUCCESS;21392140case SLJIT_OR:2141EMIT_LOGICAL(ORI, OR);2142return SLJIT_SUCCESS;21432144case SLJIT_XOR:2145if (!(flags & LOGICAL_OP)) {2146SLJIT_ASSERT((flags & SRC2_IMM) && src2 == -1);2147if (op & SLJIT_SET_Z)2148FAIL_IF(push_inst(compiler, NOR | S(src1) | T(src1) | DA(EQUAL_FLAG), EQUAL_FLAG));2149if (!(flags & UNUSED_DEST))2150FAIL_IF(push_inst(compiler, NOR | S(src1) | T(src1) | D(dst), DR(dst)));2151return SLJIT_SUCCESS;2152}2153EMIT_LOGICAL(XORI, XOR);2154return SLJIT_SUCCESS;21552156case SLJIT_SHL:2157case SLJIT_MSHL:2158EMIT_SHIFT(DSLL, DSLL32, SLL, DSLLV, SLLV);2159break;21602161case SLJIT_LSHR:2162case SLJIT_MLSHR:2163EMIT_SHIFT(DSRL, DSRL32, SRL, DSRLV, SRLV);2164break;21652166case SLJIT_ASHR:2167case SLJIT_MASHR:2168EMIT_SHIFT(DSRA, DSRA32, SRA, DSRAV, SRAV);2169break;21702171#if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 2)2172case SLJIT_ROTL:2173if ((flags & SRC2_IMM) || src2 == 0) {2174#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)2175src2 = -src2 & 0x1f;2176#else /* !SLJIT_CONFIG_MIPS_32 */2177src2 = -src2 & ((op & SLJIT_32) ? 0x1f : 0x3f);2178#endif /* SLJIT_CONFIG_MIPS_32 */2179} else {2180FAIL_IF(push_inst(compiler, SELECT_OP(DSUBU, SUBU) | SA(0) | T(src2) | D(TMP_REG2), DR(TMP_REG2)));2181src2 = TMP_REG2;2182}2183SLJIT_FALLTHROUGH21842185case SLJIT_ROTR:2186EMIT_SHIFT(DROTR, DROTR32, ROTR, DROTRV, ROTRV);2187break;2188#else /* SLJIT_MIPS_REV < 1 */2189case SLJIT_ROTL:2190case SLJIT_ROTR:2191if (flags & SRC2_IMM) {2192SLJIT_ASSERT(src2 != 0);2193#if (defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64)2194if (!(op & SLJIT_32)) {2195if (GET_OPCODE(op) == SLJIT_ROTL)2196op_imm = ((src2 < 32) ? DSLL : DSLL32);2197else2198op_imm = ((src2 < 32) ? DSRL : DSRL32);21992200FAIL_IF(push_inst(compiler, op_imm | T(src1) | DA(OTHER_FLAG) | (((sljit_ins)src2 & 0x1f) << 6), OTHER_FLAG));22012202src2 = 64 - src2;2203if (GET_OPCODE(op) == SLJIT_ROTL)2204op_imm = ((src2 < 32) ? DSRL : DSRL32);2205else2206op_imm = ((src2 < 32) ? DSLL : DSLL32);22072208FAIL_IF(push_inst(compiler, op_imm | T(src1) | D(dst) | (((sljit_ins)src2 & 0x1f) << 6), DR(dst)));2209return push_inst(compiler, OR | S(dst) | TA(OTHER_FLAG) | D(dst), DR(dst));2210}2211#endif /* SLJIT_CONFIG_MIPS_64 */22122213op_imm = (GET_OPCODE(op) == SLJIT_ROTL) ? SLL : SRL;2214FAIL_IF(push_inst(compiler, op_imm | T(src1) | DA(OTHER_FLAG) | ((sljit_ins)src2 << 6), OTHER_FLAG));22152216src2 = 32 - src2;2217op_imm = (GET_OPCODE(op) == SLJIT_ROTL) ? SRL : SLL;2218FAIL_IF(push_inst(compiler, op_imm | T(src1) | D(dst) | (((sljit_ins)src2 & 0x1f) << 6), DR(dst)));2219return push_inst(compiler, OR | S(dst) | TA(OTHER_FLAG) | D(dst), DR(dst));2220}22212222if (src2 == 0) {2223if (dst != src1)2224return push_inst(compiler, SELECT_OP(DADDU, ADDU) | S(src1) | TA(0) | D(dst), DR(dst));2225return SLJIT_SUCCESS;2226}22272228FAIL_IF(push_inst(compiler, SELECT_OP(DSUBU, SUBU) | SA(0) | T(src2) | DA(EQUAL_FLAG), EQUAL_FLAG));22292230#if (defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64)2231if (!(op & SLJIT_32)) {2232op_v = (GET_OPCODE(op) == SLJIT_ROTL) ? DSLLV : DSRLV;2233FAIL_IF(push_inst(compiler, op_v | S(src2) | T(src1) | DA(OTHER_FLAG), OTHER_FLAG));2234op_v = (GET_OPCODE(op) == SLJIT_ROTL) ? DSRLV : DSLLV;2235FAIL_IF(push_inst(compiler, op_v | SA(EQUAL_FLAG) | T(src1) | D(dst), DR(dst)));2236return push_inst(compiler, OR | S(dst) | TA(OTHER_FLAG) | D(dst), DR(dst));2237}2238#endif /* SLJIT_CONFIG_MIPS_64 */22392240op_v = (GET_OPCODE(op) == SLJIT_ROTL) ? SLLV : SRLV;2241FAIL_IF(push_inst(compiler, op_v | S(src2) | T(src1) | DA(OTHER_FLAG), OTHER_FLAG));2242op_v = (GET_OPCODE(op) == SLJIT_ROTL) ? SRLV : SLLV;2243FAIL_IF(push_inst(compiler, op_v | SA(EQUAL_FLAG) | T(src1) | D(dst), DR(dst)));2244return push_inst(compiler, OR | S(dst) | TA(OTHER_FLAG) | D(dst), DR(dst));2245#endif /* SLJIT_MIPS_REV >= 2 */22462247default:2248SLJIT_UNREACHABLE();2249return SLJIT_SUCCESS;2250}22512252#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)2253if ((flags & SRC2_IMM) || src2 == 0) {2254if (op & SLJIT_SET_Z)2255FAIL_IF(push_inst(compiler, op_imm | T(src1) | DA(EQUAL_FLAG) | SH_IMM(src2), EQUAL_FLAG));22562257if (flags & UNUSED_DEST)2258return SLJIT_SUCCESS;2259return push_inst(compiler, op_imm | T(src1) | D(dst) | SH_IMM(src2), DR(dst));2260}22612262if (op & SLJIT_SET_Z)2263FAIL_IF(push_inst(compiler, op_v | S(src2) | T(src1) | DA(EQUAL_FLAG), EQUAL_FLAG));22642265if (flags & UNUSED_DEST)2266return SLJIT_SUCCESS;2267return push_inst(compiler, op_v | S(src2) | T(src1) | D(dst), DR(dst));2268#else /* !SLJIT_CONFIG_MIPS_32 */2269if ((flags & SRC2_IMM) || src2 == 0) {2270if (src2 >= 32) {2271SLJIT_ASSERT(!(op & SLJIT_32));2272ins = op_dimm32;2273src2 -= 32;2274}2275else2276ins = (op & SLJIT_32) ? op_imm : op_dimm;22772278if (op & SLJIT_SET_Z)2279FAIL_IF(push_inst(compiler, ins | T(src1) | DA(EQUAL_FLAG) | SH_IMM(src2), EQUAL_FLAG));22802281if (flags & UNUSED_DEST)2282return SLJIT_SUCCESS;2283return push_inst(compiler, ins | T(src1) | D(dst) | SH_IMM(src2), DR(dst));2284}22852286ins = (op & SLJIT_32) ? op_v : op_dv;2287if (op & SLJIT_SET_Z)2288FAIL_IF(push_inst(compiler, ins | S(src2) | T(src1) | DA(EQUAL_FLAG), EQUAL_FLAG));22892290if (flags & UNUSED_DEST)2291return SLJIT_SUCCESS;2292return push_inst(compiler, ins | S(src2) | T(src1) | D(dst), DR(dst));2293#endif /* SLJIT_CONFIG_MIPS_32 */2294}22952296#define CHECK_IMM(flags, srcw) \2297((!((flags) & LOGICAL_OP) && ((srcw) <= SIMM_MAX && (srcw) >= SIMM_MIN)) \2298|| (((flags) & LOGICAL_OP) && !((srcw) & ~UIMM_MAX)))22992300static sljit_s32 emit_op(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 flags,2301sljit_s32 dst, sljit_sw dstw,2302sljit_s32 src1, sljit_sw src1w,2303sljit_s32 src2, sljit_sw src2w)2304{2305/* arg1 goes to TMP_REG1 or src reg2306arg2 goes to TMP_REG2, imm or src reg2307TMP_REG3 can be used for caching2308result goes to TMP_REG2, so put result can use TMP_REG1 and TMP_REG3. */2309sljit_s32 dst_r = TMP_REG2;2310sljit_s32 src1_r;2311sljit_sw src2_r = 0;2312sljit_s32 src2_tmp_reg = (GET_OPCODE(op) >= SLJIT_OP2_BASE && FAST_IS_REG(src1)) ? TMP_REG1 : TMP_REG2;23132314if (!(flags & ALT_KEEP_CACHE)) {2315compiler->cache_arg = 0;2316compiler->cache_argw = 0;2317}23182319if (dst == 0) {2320SLJIT_ASSERT(HAS_FLAGS(op));2321flags |= UNUSED_DEST;2322dst = TMP_REG2;2323}2324else if (FAST_IS_REG(dst)) {2325dst_r = dst;2326flags |= REG_DEST;2327if (flags & MOVE_OP)2328src2_tmp_reg = dst_r;2329}2330else if ((dst & SLJIT_MEM) && !getput_arg_fast(compiler, flags | ARG_TEST, DR(TMP_REG1), dst, dstw))2331flags |= SLOW_DEST;23322333if (flags & IMM_OP) {2334if (src2 == SLJIT_IMM && src2w != 0 && CHECK_IMM(flags, src2w)) {2335flags |= SRC2_IMM;2336src2_r = src2w;2337} else if ((flags & CUMULATIVE_OP) && src1 == SLJIT_IMM && src1w != 0 && CHECK_IMM(flags, src1w)) {2338flags |= SRC2_IMM;2339src2_r = src1w;23402341/* And swap arguments. */2342src1 = src2;2343src1w = src2w;2344src2 = SLJIT_IMM;2345/* src2w = src2_r unneeded. */2346}2347}23482349/* Source 1. */2350if (FAST_IS_REG(src1)) {2351src1_r = src1;2352flags |= REG1_SOURCE;2353}2354else if (src1 == SLJIT_IMM) {2355if (src1w) {2356FAIL_IF(load_immediate(compiler, DR(TMP_REG1), src1w));2357src1_r = TMP_REG1;2358}2359else2360src1_r = 0;2361}2362else {2363if (getput_arg_fast(compiler, flags | LOAD_DATA, DR(TMP_REG1), src1, src1w))2364FAIL_IF(compiler->error);2365else2366flags |= SLOW_SRC1;2367src1_r = TMP_REG1;2368}23692370/* Source 2. */2371if (FAST_IS_REG(src2)) {2372src2_r = src2;2373flags |= REG2_SOURCE;2374if ((flags & (REG_DEST | MOVE_OP)) == MOVE_OP)2375dst_r = (sljit_s32)src2_r;2376}2377else if (src2 == SLJIT_IMM) {2378if (!(flags & SRC2_IMM)) {2379if (src2w) {2380FAIL_IF(load_immediate(compiler, DR(src2_tmp_reg), src2w));2381src2_r = src2_tmp_reg;2382}2383else {2384src2_r = 0;2385if (flags & MOVE_OP) {2386if (dst & SLJIT_MEM)2387dst_r = 0;2388else2389op = SLJIT_MOV;2390}2391}2392}2393}2394else {2395if (getput_arg_fast(compiler, flags | LOAD_DATA, DR(src2_tmp_reg), src2, src2w))2396FAIL_IF(compiler->error);2397else2398flags |= SLOW_SRC2;2399src2_r = src2_tmp_reg;2400}24012402if ((flags & (SLOW_SRC1 | SLOW_SRC2)) == (SLOW_SRC1 | SLOW_SRC2)) {2403SLJIT_ASSERT(src2_r == TMP_REG2);2404if ((flags & SLOW_DEST) && !can_cache(src1, src1w, src2, src2w) && can_cache(src1, src1w, dst, dstw)) {2405FAIL_IF(getput_arg(compiler, flags | LOAD_DATA, DR(TMP_REG2), src2, src2w, src1, src1w));2406FAIL_IF(getput_arg(compiler, flags | LOAD_DATA, DR(TMP_REG1), src1, src1w, dst, dstw));2407}2408else {2409FAIL_IF(getput_arg(compiler, flags | LOAD_DATA, DR(TMP_REG1), src1, src1w, src2, src2w));2410FAIL_IF(getput_arg(compiler, flags | LOAD_DATA, DR(TMP_REG2), src2, src2w, dst, dstw));2411}2412}2413else if (flags & SLOW_SRC1)2414FAIL_IF(getput_arg(compiler, flags | LOAD_DATA, DR(TMP_REG1), src1, src1w, dst, dstw));2415else if (flags & SLOW_SRC2)2416FAIL_IF(getput_arg(compiler, flags | LOAD_DATA, DR(src2_tmp_reg), src2, src2w, dst, dstw));24172418FAIL_IF(emit_single_op(compiler, op, flags, dst_r, src1_r, src2_r));24192420if (dst & SLJIT_MEM) {2421if (!(flags & SLOW_DEST)) {2422getput_arg_fast(compiler, flags, DR(dst_r), dst, dstw);2423return compiler->error;2424}2425return getput_arg(compiler, flags, DR(dst_r), dst, dstw, 0, 0);2426}24272428return SLJIT_SUCCESS;2429}24302431#undef CHECK_IMM24322433SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op0(struct sljit_compiler *compiler, sljit_s32 op)2434{2435#if (defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64)2436sljit_s32 int_op = op & SLJIT_32;2437#endif24382439CHECK_ERROR();2440CHECK(check_sljit_emit_op0(compiler, op));24412442op = GET_OPCODE(op);2443switch (op) {2444case SLJIT_BREAKPOINT:2445return push_inst(compiler, BREAK, UNMOVABLE_INS);2446case SLJIT_NOP:2447return push_inst(compiler, NOP, UNMOVABLE_INS);2448case SLJIT_LMUL_UW:2449case SLJIT_LMUL_SW:2450#if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 6)2451#if (defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64)2452FAIL_IF(push_inst(compiler, (op == SLJIT_LMUL_UW ? DMULU : DMUL) | S(SLJIT_R0) | T(SLJIT_R1) | D(TMP_REG3), DR(TMP_REG3)));2453FAIL_IF(push_inst(compiler, (op == SLJIT_LMUL_UW ? DMUHU : DMUH) | S(SLJIT_R0) | T(SLJIT_R1) | D(TMP_REG1), DR(TMP_REG1)));2454#else /* !SLJIT_CONFIG_MIPS_64 */2455FAIL_IF(push_inst(compiler, (op == SLJIT_LMUL_UW ? MULU : MUL) | S(SLJIT_R0) | T(SLJIT_R1) | D(TMP_REG3), DR(TMP_REG3)));2456FAIL_IF(push_inst(compiler, (op == SLJIT_LMUL_UW ? MUHU : MUH) | S(SLJIT_R0) | T(SLJIT_R1) | D(TMP_REG1), DR(TMP_REG1)));2457#endif /* SLJIT_CONFIG_MIPS_64 */2458FAIL_IF(push_inst(compiler, ADDU_W | S(TMP_REG3) | TA(0) | D(SLJIT_R0), DR(SLJIT_R0)));2459return push_inst(compiler, ADDU_W | S(TMP_REG1) | TA(0) | D(SLJIT_R1), DR(SLJIT_R1));2460#else /* SLJIT_MIPS_REV < 6 */2461#if (defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64)2462FAIL_IF(push_inst(compiler, (op == SLJIT_LMUL_UW ? DMULTU : DMULT) | S(SLJIT_R0) | T(SLJIT_R1), MOVABLE_INS));2463#else /* !SLJIT_CONFIG_MIPS_64 */2464FAIL_IF(push_inst(compiler, (op == SLJIT_LMUL_UW ? MULTU : MULT) | S(SLJIT_R0) | T(SLJIT_R1), MOVABLE_INS));2465#endif /* SLJIT_CONFIG_MIPS_64 */2466FAIL_IF(push_inst(compiler, MFLO | D(SLJIT_R0), DR(SLJIT_R0)));2467return push_inst(compiler, MFHI | D(SLJIT_R1), DR(SLJIT_R1));2468#endif /* SLJIT_MIPS_REV >= 6 */2469case SLJIT_DIVMOD_UW:2470case SLJIT_DIVMOD_SW:2471case SLJIT_DIV_UW:2472case SLJIT_DIV_SW:2473SLJIT_COMPILE_ASSERT((SLJIT_DIVMOD_UW & 0x2) == 0 && SLJIT_DIV_UW - 0x2 == SLJIT_DIVMOD_UW, bad_div_opcode_assignments);2474#if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 6)2475#if (defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64)2476if (int_op) {2477FAIL_IF(push_inst(compiler, ((op | 0x2) == SLJIT_DIV_UW ? DIVU : DIV) | S(SLJIT_R0) | T(SLJIT_R1) | D(TMP_REG3), DR(TMP_REG3)));2478FAIL_IF(push_inst(compiler, ((op | 0x2) == SLJIT_DIV_UW ? MODU : MOD) | S(SLJIT_R0) | T(SLJIT_R1) | D(TMP_REG1), DR(TMP_REG1)));2479}2480else {2481FAIL_IF(push_inst(compiler, ((op | 0x2) == SLJIT_DIV_UW ? DDIVU : DDIV) | S(SLJIT_R0) | T(SLJIT_R1) | D(TMP_REG3), DR(TMP_REG3)));2482FAIL_IF(push_inst(compiler, ((op | 0x2) == SLJIT_DIV_UW ? DMODU : DMOD) | S(SLJIT_R0) | T(SLJIT_R1) | D(TMP_REG1), DR(TMP_REG1)));2483}2484#else /* !SLJIT_CONFIG_MIPS_64 */2485FAIL_IF(push_inst(compiler, ((op | 0x2) == SLJIT_DIV_UW ? DIVU : DIV) | S(SLJIT_R0) | T(SLJIT_R1) | D(TMP_REG3), DR(TMP_REG3)));2486FAIL_IF(push_inst(compiler, ((op | 0x2) == SLJIT_DIV_UW ? MODU : MOD) | S(SLJIT_R0) | T(SLJIT_R1) | D(TMP_REG1), DR(TMP_REG1)));2487#endif /* SLJIT_CONFIG_MIPS_64 */2488FAIL_IF(push_inst(compiler, ADDU_W | S(TMP_REG3) | TA(0) | D(SLJIT_R0), DR(SLJIT_R0)));2489return (op >= SLJIT_DIV_UW) ? SLJIT_SUCCESS : push_inst(compiler, ADDU_W | S(TMP_REG1) | TA(0) | D(SLJIT_R1), DR(SLJIT_R1));2490#else /* SLJIT_MIPS_REV < 6 */2491#if !(defined SLJIT_MIPS_REV)2492FAIL_IF(push_inst(compiler, NOP, UNMOVABLE_INS));2493FAIL_IF(push_inst(compiler, NOP, UNMOVABLE_INS));2494#endif /* !SLJIT_MIPS_REV */2495#if (defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64)2496if (int_op)2497FAIL_IF(push_inst(compiler, ((op | 0x2) == SLJIT_DIV_UW ? DIVU : DIV) | S(SLJIT_R0) | T(SLJIT_R1), MOVABLE_INS));2498else2499FAIL_IF(push_inst(compiler, ((op | 0x2) == SLJIT_DIV_UW ? DDIVU : DDIV) | S(SLJIT_R0) | T(SLJIT_R1), MOVABLE_INS));2500#else /* !SLJIT_CONFIG_MIPS_64 */2501FAIL_IF(push_inst(compiler, ((op | 0x2) == SLJIT_DIV_UW ? DIVU : DIV) | S(SLJIT_R0) | T(SLJIT_R1), MOVABLE_INS));2502#endif /* SLJIT_CONFIG_MIPS_64 */2503FAIL_IF(push_inst(compiler, MFLO | D(SLJIT_R0), DR(SLJIT_R0)));2504return (op >= SLJIT_DIV_UW) ? SLJIT_SUCCESS : push_inst(compiler, MFHI | D(SLJIT_R1), DR(SLJIT_R1));2505#endif /* SLJIT_MIPS_REV >= 6 */2506case SLJIT_MEMORY_BARRIER:2507#if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 1)2508return push_inst(compiler, SYNC, UNMOVABLE_INS);2509#else /* SLJIT_MIPS_REV < 1 */2510return SLJIT_ERR_UNSUPPORTED;2511#endif /* SLJIT_MIPS_REV >= 1 */2512case SLJIT_ENDBR:2513case SLJIT_SKIP_FRAMES_BEFORE_RETURN:2514return SLJIT_SUCCESS;2515}25162517return SLJIT_SUCCESS;2518}25192520#if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 1)2521static sljit_s32 emit_prefetch(struct sljit_compiler *compiler,2522sljit_s32 src, sljit_sw srcw)2523{2524if (!(src & OFFS_REG_MASK)) {2525if (srcw <= SIMM_MAX && srcw >= SIMM_MIN)2526return push_inst(compiler, PREF | S(src & REG_MASK) | IMM(srcw), MOVABLE_INS);25272528FAIL_IF(load_immediate(compiler, DR(TMP_REG1), srcw));2529return push_inst(compiler, PREFX | S(src & REG_MASK) | T(TMP_REG1), MOVABLE_INS);2530}25312532srcw &= 0x3;25332534if (SLJIT_UNLIKELY(srcw != 0)) {2535FAIL_IF(push_inst(compiler, SLL_W | T(OFFS_REG(src)) | D(TMP_REG1) | SH_IMM(srcw), DR(TMP_REG1)));2536return push_inst(compiler, PREFX | S(src & REG_MASK) | T(TMP_REG1), MOVABLE_INS);2537}25382539return push_inst(compiler, PREFX | S(src & REG_MASK) | T(OFFS_REG(src)), MOVABLE_INS);2540}2541#endif /* SLJIT_MIPS_REV >= 1 */25422543SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op1(struct sljit_compiler *compiler, sljit_s32 op,2544sljit_s32 dst, sljit_sw dstw,2545sljit_s32 src, sljit_sw srcw)2546{2547sljit_s32 flags = 0;25482549CHECK_ERROR();2550CHECK(check_sljit_emit_op1(compiler, op, dst, dstw, src, srcw));2551ADJUST_LOCAL_OFFSET(dst, dstw);2552ADJUST_LOCAL_OFFSET(src, srcw);25532554#if (defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64)2555if (op & SLJIT_32)2556flags = INT_DATA | SIGNED_DATA;2557#endif25582559switch (GET_OPCODE(op)) {2560case SLJIT_MOV:2561#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)2562case SLJIT_MOV_U32:2563case SLJIT_MOV_S32:2564case SLJIT_MOV32:2565#endif2566case SLJIT_MOV_P:2567return emit_op(compiler, SLJIT_MOV, WORD_DATA | MOVE_OP, dst, dstw, TMP_REG1, 0, src, srcw);25682569#if (defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64)2570case SLJIT_MOV_U32:2571return emit_op(compiler, SLJIT_MOV_U32, INT_DATA | MOVE_OP, dst, dstw, TMP_REG1, 0, src, (src == SLJIT_IMM) ? (sljit_u32)srcw : srcw);25722573case SLJIT_MOV_S32:2574case SLJIT_MOV32:2575return 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);2576#endif25772578case SLJIT_MOV_U8:2579return emit_op(compiler, op, BYTE_DATA | MOVE_OP, dst, dstw, TMP_REG1, 0, src, (src == SLJIT_IMM) ? (sljit_u8)srcw : srcw);25802581case SLJIT_MOV_S8:2582return emit_op(compiler, op, BYTE_DATA | SIGNED_DATA | MOVE_OP, dst, dstw, TMP_REG1, 0, src, (src == SLJIT_IMM) ? (sljit_s8)srcw : srcw);25832584case SLJIT_MOV_U16:2585return emit_op(compiler, op, HALF_DATA | MOVE_OP, dst, dstw, TMP_REG1, 0, src, (src == SLJIT_IMM) ? (sljit_u16)srcw : srcw);25862587case SLJIT_MOV_S16:2588return emit_op(compiler, op, HALF_DATA | SIGNED_DATA | MOVE_OP, dst, dstw, TMP_REG1, 0, src, (src == SLJIT_IMM) ? (sljit_s16)srcw : srcw);25892590case SLJIT_CLZ:2591case SLJIT_CTZ:2592case SLJIT_REV:2593return emit_op(compiler, op, flags, dst, dstw, TMP_REG1, 0, src, srcw);25942595case SLJIT_REV_U16:2596case SLJIT_REV_S16:2597return emit_op(compiler, op, HALF_DATA, dst, dstw, TMP_REG1, 0, src, srcw);25982599case SLJIT_REV_U32:2600case SLJIT_REV_S32:2601return emit_op(compiler, op | SLJIT_32, INT_DATA, dst, dstw, TMP_REG1, 0, src, srcw);2602}26032604SLJIT_UNREACHABLE();2605return SLJIT_SUCCESS;2606}26072608SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op2(struct sljit_compiler *compiler, sljit_s32 op,2609sljit_s32 dst, sljit_sw dstw,2610sljit_s32 src1, sljit_sw src1w,2611sljit_s32 src2, sljit_sw src2w)2612{2613sljit_s32 flags = 0;26142615CHECK_ERROR();2616CHECK(check_sljit_emit_op2(compiler, op, 0, dst, dstw, src1, src1w, src2, src2w));2617ADJUST_LOCAL_OFFSET(dst, dstw);2618ADJUST_LOCAL_OFFSET(src1, src1w);2619ADJUST_LOCAL_OFFSET(src2, src2w);26202621#if (defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64)2622if (op & SLJIT_32) {2623flags |= INT_DATA | SIGNED_DATA;2624if (src1 == SLJIT_IMM)2625src1w = (sljit_s32)src1w;2626if (src2 == SLJIT_IMM)2627src2w = (sljit_s32)src2w;2628}2629#endif26302631switch (GET_OPCODE(op)) {2632case SLJIT_ADD:2633case SLJIT_ADDC:2634compiler->status_flags_state = SLJIT_CURRENT_FLAGS_ADD;2635return emit_op(compiler, op, flags | CUMULATIVE_OP | IMM_OP, dst, dstw, src1, src1w, src2, src2w);26362637case SLJIT_SUB:2638case SLJIT_SUBC:2639compiler->status_flags_state = SLJIT_CURRENT_FLAGS_SUB;2640return emit_op(compiler, op, flags | IMM_OP, dst, dstw, src1, src1w, src2, src2w);26412642case SLJIT_MUL:2643compiler->status_flags_state = 0;2644return emit_op(compiler, op, flags | CUMULATIVE_OP, dst, dstw, src1, src1w, src2, src2w);26452646case SLJIT_XOR:2647if ((src1 == SLJIT_IMM && src1w == -1) || (src2 == SLJIT_IMM && src2w == -1)) {2648return emit_op(compiler, op, flags | CUMULATIVE_OP | IMM_OP, dst, dstw, src1, src1w, src2, src2w);2649}2650SLJIT_FALLTHROUGH2651case SLJIT_AND:2652case SLJIT_OR:2653return emit_op(compiler, op, flags | CUMULATIVE_OP | LOGICAL_OP | IMM_OP, dst, dstw, src1, src1w, src2, src2w);26542655case SLJIT_SHL:2656case SLJIT_MSHL:2657case SLJIT_LSHR:2658case SLJIT_MLSHR:2659case SLJIT_ASHR:2660case SLJIT_MASHR:2661case SLJIT_ROTL:2662case SLJIT_ROTR:2663#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)2664if (src2 == SLJIT_IMM)2665src2w &= 0x1f;2666#else2667if (src2 == SLJIT_IMM) {2668if (op & SLJIT_32)2669src2w &= 0x1f;2670else2671src2w &= 0x3f;2672}2673#endif2674return emit_op(compiler, op, flags | IMM_OP, dst, dstw, src1, src1w, src2, src2w);2675}26762677SLJIT_UNREACHABLE();2678return SLJIT_SUCCESS;2679}26802681SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op2u(struct sljit_compiler *compiler, sljit_s32 op,2682sljit_s32 src1, sljit_sw src1w,2683sljit_s32 src2, sljit_sw src2w)2684{2685CHECK_ERROR();2686CHECK(check_sljit_emit_op2(compiler, op, 1, 0, 0, src1, src1w, src2, src2w));26872688SLJIT_SKIP_CHECKS(compiler);2689return sljit_emit_op2(compiler, op, 0, 0, src1, src1w, src2, src2w);2690}26912692#if (defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64)2693#define SELECT_OP3(op, src2w, D, D32, W) (((op & SLJIT_32) ? (W) : ((src2w) < 32) ? (D) : (D32)) | (((sljit_ins)src2w & 0x1f) << 6))2694#else /* !SLJIT_CONFIG_MIPS_64 */2695#define SELECT_OP3(op, src2w, D, D32, W) ((W) | ((sljit_ins)(src2w) << 6))2696#endif /* SLJIT_CONFIG_MIPS_64 */26972698SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op2r(struct sljit_compiler *compiler, sljit_s32 op,2699sljit_s32 dst_reg,2700sljit_s32 src1, sljit_sw src1w,2701sljit_s32 src2, sljit_sw src2w)2702{2703CHECK_ERROR();2704CHECK(check_sljit_emit_op2r(compiler, op, dst_reg, src1, src1w, src2, src2w));27052706switch (GET_OPCODE(op)) {2707case SLJIT_MULADD:2708SLJIT_SKIP_CHECKS(compiler);2709FAIL_IF(sljit_emit_op2(compiler, SLJIT_MUL | (op & SLJIT_32), TMP_REG2, 0, src1, src1w, src2, src2w));2710return push_inst(compiler, SELECT_OP(DADDU, ADDU) | S(dst_reg) | T(TMP_REG2) | D(dst_reg), DR(dst_reg));2711}27122713return SLJIT_SUCCESS;2714}27152716SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_shift_into(struct sljit_compiler *compiler, sljit_s32 op,2717sljit_s32 dst_reg,2718sljit_s32 src1_reg,2719sljit_s32 src2_reg,2720sljit_s32 src3, sljit_sw src3w)2721{2722sljit_s32 is_left;2723sljit_ins ins1, ins2, ins3;2724#if (defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64)2725sljit_s32 inp_flags = ((op & SLJIT_32) ? INT_DATA : WORD_DATA) | LOAD_DATA;2726sljit_sw bit_length = (op & SLJIT_32) ? 32 : 64;2727#else /* !SLJIT_CONFIG_MIPS_64 */2728sljit_s32 inp_flags = WORD_DATA | LOAD_DATA;2729sljit_sw bit_length = 32;2730#endif /* SLJIT_CONFIG_MIPS_64 */27312732CHECK_ERROR();2733CHECK(check_sljit_emit_shift_into(compiler, op, dst_reg, src1_reg, src2_reg, src3, src3w));27342735is_left = (GET_OPCODE(op) == SLJIT_SHL || GET_OPCODE(op) == SLJIT_MSHL);27362737if (src1_reg == src2_reg) {2738SLJIT_SKIP_CHECKS(compiler);2739return sljit_emit_op2(compiler, (is_left ? SLJIT_ROTL : SLJIT_ROTR) | (op & SLJIT_32), dst_reg, 0, src1_reg, 0, src3, src3w);2740}27412742ADJUST_LOCAL_OFFSET(src3, src3w);27432744if (src3 == SLJIT_IMM) {2745src3w &= bit_length - 1;27462747if (src3w == 0)2748return SLJIT_SUCCESS;27492750if (is_left) {2751ins1 = SELECT_OP3(op, src3w, DSLL, DSLL32, SLL);2752src3w = bit_length - src3w;2753ins2 = SELECT_OP3(op, src3w, DSRL, DSRL32, SRL);2754} else {2755ins1 = SELECT_OP3(op, src3w, DSRL, DSRL32, SRL);2756src3w = bit_length - src3w;2757ins2 = SELECT_OP3(op, src3w, DSLL, DSLL32, SLL);2758}27592760FAIL_IF(push_inst(compiler, ins1 | T(src1_reg) | D(dst_reg), DR(dst_reg)));2761FAIL_IF(push_inst(compiler, ins2 | T(src2_reg) | D(TMP_REG1), DR(TMP_REG1)));2762return push_inst(compiler, OR | S(dst_reg) | T(TMP_REG1) | D(dst_reg), DR(dst_reg));2763}27642765if (src3 & SLJIT_MEM) {2766FAIL_IF(emit_op_mem(compiler, inp_flags, DR(TMP_REG2), src3, src3w));2767src3 = TMP_REG2;2768} else if (dst_reg == src3) {2769FAIL_IF(push_inst(compiler, SELECT_OP(DADDU, ADDU) | S(src3) | TA(0) | D(TMP_REG2), DR(TMP_REG2)));2770src3 = TMP_REG2;2771}27722773if (is_left) {2774ins1 = SELECT_OP(DSRL, SRL);2775ins2 = SELECT_OP(DSLLV, SLLV);2776ins3 = SELECT_OP(DSRLV, SRLV);2777} else {2778ins1 = SELECT_OP(DSLL, SLL);2779ins2 = SELECT_OP(DSRLV, SRLV);2780ins3 = SELECT_OP(DSLLV, SLLV);2781}27822783FAIL_IF(push_inst(compiler, ins2 | S(src3) | T(src1_reg) | D(dst_reg), DR(dst_reg)));27842785if (!(op & SLJIT_SHIFT_INTO_NON_ZERO)) {2786FAIL_IF(push_inst(compiler, ins1 | T(src2_reg) | D(TMP_REG1) | (1 << 6), DR(TMP_REG1)));2787FAIL_IF(push_inst(compiler, XORI | S(src3) | T(TMP_REG2) | ((sljit_ins)bit_length - 1), DR(TMP_REG2)));2788src2_reg = TMP_REG1;2789} else2790FAIL_IF(push_inst(compiler, SELECT_OP(DSUBU, SUBU) | SA(0) | T(src3) | D(TMP_REG2), DR(TMP_REG2)));27912792FAIL_IF(push_inst(compiler, ins3 | S(TMP_REG2) | T(src2_reg) | D(TMP_REG1), DR(TMP_REG1)));2793return push_inst(compiler, OR | S(dst_reg) | T(TMP_REG1) | D(dst_reg), DR(dst_reg));2794}27952796SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op2_shift(struct sljit_compiler *compiler, sljit_s32 op,2797sljit_s32 dst, sljit_sw dstw,2798sljit_s32 src1, sljit_sw src1w,2799sljit_s32 src2, sljit_sw src2w,2800sljit_sw shift_arg)2801{2802sljit_s32 dst_r, tmp_r;28032804CHECK_ERROR();2805CHECK(check_sljit_emit_op2_shift(compiler, op, dst, dstw, src1, src1w, src2, src2w, shift_arg));2806ADJUST_LOCAL_OFFSET(dst, dstw);2807ADJUST_LOCAL_OFFSET(src1, src1w);2808ADJUST_LOCAL_OFFSET(src2, src2w);28092810shift_arg &= (sljit_sw)((sizeof(sljit_sw) * 8) - 1);28112812if (src2 == SLJIT_IMM) {2813src2w = src2w << shift_arg;2814shift_arg = 0;2815}28162817if (shift_arg == 0) {2818SLJIT_SKIP_CHECKS(compiler);2819return sljit_emit_op2(compiler, GET_OPCODE(op), dst, dstw, src1, src1w, src2, src2w);2820}28212822if (src2 & SLJIT_MEM) {2823FAIL_IF(emit_op_mem2(compiler, WORD_DATA | LOAD_DATA, DR(TMP_REG2), src2, src2w, src1, src1w));2824src2 = TMP_REG2;2825}28262827if (src1 == SLJIT_IMM) {2828FAIL_IF(load_immediate(compiler, DR(TMP_REG1), src1w));2829src1 = TMP_REG1;2830} else if (src1 & SLJIT_MEM) {2831FAIL_IF(emit_op_mem2(compiler, WORD_DATA | LOAD_DATA, DR(TMP_REG1), src1, src1w, dst, dstw));2832src1 = TMP_REG1;2833}28342835dst_r = FAST_IS_REG(dst) ? dst : TMP_REG2;2836tmp_r = (src1 == TMP_REG1) ? TMP_REG2 : TMP_REG1;2837#if (defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64)2838FAIL_IF(push_inst(compiler, (shift_arg >= 32 ? DSLL32 : DSLL) | T(src2) | D(tmp_r) | SH_IMM(shift_arg & 0x1f), DR(tmp_r)));2839#else /* !SLJIT_CONFIG_MIPS_64 */2840FAIL_IF(push_inst(compiler, SLL | T(src2) | D(tmp_r) | SH_IMM(shift_arg), DR(tmp_r)));2841#endif /* SLJIT_CONFIG_MIPS_64 */2842FAIL_IF(push_inst(compiler, ADDU_W | S(src1) | T(tmp_r) | D(dst_r), DR(dst_r)));28432844if (dst & SLJIT_MEM)2845return emit_op_mem2(compiler, WORD_DATA, DR(dst_r), dst, dstw, 0, 0);2846return SLJIT_SUCCESS;2847}28482849#undef SELECT_OP328502851SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_src(struct sljit_compiler *compiler, sljit_s32 op,2852sljit_s32 src, sljit_sw srcw)2853{2854CHECK_ERROR();2855CHECK(check_sljit_emit_op_src(compiler, op, src, srcw));2856ADJUST_LOCAL_OFFSET(src, srcw);28572858switch (op) {2859case SLJIT_FAST_RETURN:2860if (FAST_IS_REG(src)) {2861if (DR(src) != RETURN_ADDR_REG)2862FAIL_IF(push_inst(compiler, ADDU_W | S(src) | TA(0) | DA(RETURN_ADDR_REG), RETURN_ADDR_REG));2863} else2864FAIL_IF(emit_op_mem(compiler, WORD_DATA | LOAD_DATA, RETURN_ADDR_REG, src, srcw));28652866FAIL_IF(push_inst(compiler, JR | SA(RETURN_ADDR_REG), UNMOVABLE_INS));2867return push_inst(compiler, NOP, UNMOVABLE_INS);2868case SLJIT_SKIP_FRAMES_BEFORE_FAST_RETURN:2869return SLJIT_SUCCESS;2870case SLJIT_PREFETCH_L1:2871case SLJIT_PREFETCH_L2:2872case SLJIT_PREFETCH_L3:2873case SLJIT_PREFETCH_ONCE:2874#if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 1)2875return emit_prefetch(compiler, src, srcw);2876#else /* SLJIT_MIPS_REV < 1 */2877return SLJIT_SUCCESS;2878#endif /* SLJIT_MIPS_REV >= 1 */2879}28802881return SLJIT_SUCCESS;2882}28832884SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_dst(struct sljit_compiler *compiler, sljit_s32 op,2885sljit_s32 dst, sljit_sw dstw)2886{2887sljit_s32 dst_ar = RETURN_ADDR_REG;28882889CHECK_ERROR();2890CHECK(check_sljit_emit_op_dst(compiler, op, dst, dstw));2891ADJUST_LOCAL_OFFSET(dst, dstw);28922893switch (op) {2894case SLJIT_FAST_ENTER:2895if (FAST_IS_REG(dst)) {2896if (DR(dst) == RETURN_ADDR_REG)2897return SLJIT_SUCCESS;2898return push_inst(compiler, ADDU_W | SA(RETURN_ADDR_REG) | TA(0) | D(dst), UNMOVABLE_INS);2899}2900break;2901case SLJIT_GET_RETURN_ADDRESS:2902dst_ar = DR(FAST_IS_REG(dst) ? dst : TMP_REG2);2903FAIL_IF(emit_op_mem(compiler, WORD_DATA | LOAD_DATA, dst_ar, SLJIT_MEM1(SLJIT_SP), compiler->local_size - SSIZE_OF(sw)));2904break;2905}29062907if (dst & SLJIT_MEM) {2908FAIL_IF(emit_op_mem(compiler, WORD_DATA, dst_ar, dst, dstw));29092910if (op == SLJIT_FAST_ENTER)2911compiler->delay_slot = UNMOVABLE_INS;2912}29132914return SLJIT_SUCCESS;2915}29162917SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_get_register_index(sljit_s32 type, sljit_s32 reg)2918{2919CHECK_REG_INDEX(check_sljit_get_register_index(type, reg));29202921if (type == SLJIT_GP_REGISTER)2922return reg_map[reg];29232924if (type != SLJIT_FLOAT_REGISTER)2925return -1;29262927return FR(reg);2928}29292930SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_custom(struct sljit_compiler *compiler,2931void *instruction, sljit_u32 size)2932{2933SLJIT_UNUSED_ARG(size);29342935CHECK_ERROR();2936CHECK(check_sljit_emit_op_custom(compiler, instruction, size));29372938return push_inst(compiler, *(sljit_ins*)instruction, UNMOVABLE_INS);2939}29402941/* --------------------------------------------------------------------- */2942/* Floating point operators */2943/* --------------------------------------------------------------------- */29442945#define FLOAT_DATA(op) (DOUBLE_DATA | ((op & SLJIT_32) >> 7))2946#define FMT(op) (FMT_S | (~(sljit_ins)op & SLJIT_32) << (21 - (5 + 3)))29472948static SLJIT_INLINE sljit_s32 sljit_emit_fop1_conv_sw_from_f64(struct sljit_compiler *compiler, sljit_s32 op,2949sljit_s32 dst, sljit_sw dstw,2950sljit_s32 src, sljit_sw srcw)2951{2952#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)2953sljit_u32 flags = 0;2954#else2955sljit_u32 flags = ((sljit_u32)(GET_OPCODE(op) == SLJIT_CONV_SW_FROM_F64)) << 21;2956#endif29572958if (src & SLJIT_MEM) {2959FAIL_IF(emit_op_mem2(compiler, FLOAT_DATA(op) | LOAD_DATA, FR(TMP_FREG1), src, srcw, dst, dstw));2960src = TMP_FREG1;2961}29622963FAIL_IF(push_inst(compiler, (TRUNC_W_S ^ (flags >> 19)) | FMT(op) | FS(src) | FD(TMP_FREG1), MOVABLE_INS));29642965if (FAST_IS_REG(dst)) {2966FAIL_IF(push_inst(compiler, MFC1 | flags | T(dst) | FS(TMP_FREG1), MOVABLE_INS));2967#if !defined(SLJIT_MIPS_REV) || (SLJIT_CONFIG_MIPS_32 && SLJIT_MIPS_REV <= 1)2968FAIL_IF(push_inst(compiler, NOP, UNMOVABLE_INS));2969#endif /* MIPS III */2970return SLJIT_SUCCESS;2971}29722973return emit_op_mem2(compiler, flags ? DOUBLE_DATA : SINGLE_DATA, FR(TMP_FREG1), dst, dstw, 0, 0);2974}29752976static SLJIT_INLINE sljit_s32 sljit_emit_fop1_conv_f64_from_sw(struct sljit_compiler *compiler, sljit_s32 op,2977sljit_s32 dst, sljit_sw dstw,2978sljit_s32 src, sljit_sw srcw)2979{2980#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)2981sljit_u32 flags = 0;2982#else2983sljit_u32 flags = ((sljit_u32)(GET_OPCODE(op) == SLJIT_CONV_F64_FROM_SW)) << 21;2984#endif2985sljit_s32 dst_r = FAST_IS_REG(dst) ? dst : TMP_FREG1;29862987if (src & SLJIT_MEM)2988FAIL_IF(emit_op_mem2(compiler, (flags ? DOUBLE_DATA : SINGLE_DATA) | LOAD_DATA, FR(TMP_FREG1), src, srcw, dst, dstw));2989else {2990if (src == SLJIT_IMM) {2991#if (defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64)2992if (GET_OPCODE(op) == SLJIT_CONV_F64_FROM_S32)2993srcw = (sljit_s32)srcw;2994#endif2995FAIL_IF(load_immediate(compiler, DR(TMP_REG1), srcw));2996src = TMP_REG1;2997}29982999FAIL_IF(push_inst(compiler, MTC1 | flags | T(src) | FS(TMP_FREG1), MOVABLE_INS));3000#if !defined(SLJIT_MIPS_REV) || (SLJIT_CONFIG_MIPS_32 && SLJIT_MIPS_REV <= 1)3001FAIL_IF(push_inst(compiler, NOP, UNMOVABLE_INS));3002#endif /* MIPS III */3003}30043005FAIL_IF(push_inst(compiler, CVT_S_S | flags | (4 << 21) | ((~(sljit_ins)op & SLJIT_32) >> 8) | FS(TMP_FREG1) | FD(dst_r), MOVABLE_INS));30063007if (dst & SLJIT_MEM)3008return emit_op_mem2(compiler, FLOAT_DATA(op), FR(TMP_FREG1), dst, dstw, 0, 0);3009return SLJIT_SUCCESS;3010}30113012static SLJIT_INLINE sljit_s32 sljit_emit_fop1_conv_f64_from_uw(struct sljit_compiler *compiler, sljit_s32 op,3013sljit_s32 dst, sljit_sw dstw,3014sljit_s32 src, sljit_sw srcw)3015{3016#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)3017sljit_u32 flags = 0;3018#else3019sljit_u32 flags = 1 << 21;3020#endif3021sljit_s32 dst_r = FAST_IS_REG(dst) ? dst : TMP_FREG1;30223023if (src & SLJIT_MEM) {3024FAIL_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));3025src = TMP_REG1;3026} else if (src == SLJIT_IMM) {3027#if (defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64)3028if (GET_OPCODE(op) == SLJIT_CONV_F64_FROM_U32)3029srcw = (sljit_u32)srcw;3030#endif3031FAIL_IF(load_immediate(compiler, DR(TMP_REG1), srcw));3032src = TMP_REG1;3033}30343035#if (defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64)3036if (GET_OPCODE(op) == SLJIT_CONV_F64_FROM_U32) {3037if (src != TMP_REG1) {3038FAIL_IF(push_inst(compiler, DSLL32 | T(src) | D(TMP_REG1) | SH_IMM(0), DR(TMP_REG1)));3039FAIL_IF(push_inst(compiler, DSRL32 | T(TMP_REG1) | D(TMP_REG1) | SH_IMM(0), DR(TMP_REG1)));3040}30413042FAIL_IF(push_inst(compiler, MTC1 | flags | T(TMP_REG1) | FS(TMP_FREG1), MOVABLE_INS));3043#if !defined(SLJIT_MIPS_REV)3044FAIL_IF(push_inst(compiler, NOP, UNMOVABLE_INS));3045#endif /* MIPS III */30463047FAIL_IF(push_inst(compiler, CVT_S_S | flags | (4 << 21) | ((~(sljit_ins)op & SLJIT_32) >> 8) | FS(TMP_FREG1) | FD(dst_r), MOVABLE_INS));30483049if (dst & SLJIT_MEM)3050return emit_op_mem2(compiler, FLOAT_DATA(op), FR(TMP_FREG1), dst, dstw, 0, 0);3051return SLJIT_SUCCESS;3052}3053#else /* !SLJIT_CONFIG_MIPS_64 */3054if (!(op & SLJIT_32)) {3055FAIL_IF(push_inst(compiler, SLL | T(src) | D(TMP_REG2) | SH_IMM(1), DR(TMP_REG2)));3056FAIL_IF(push_inst(compiler, SRL | T(TMP_REG2) | D(TMP_REG2) | SH_IMM(1), DR(TMP_REG2)));30573058FAIL_IF(push_inst(compiler, MTC1 | flags | T(TMP_REG2) | FS(TMP_FREG1), MOVABLE_INS));3059#if !defined(SLJIT_MIPS_REV) || SLJIT_MIPS_REV <= 13060FAIL_IF(push_inst(compiler, NOP, UNMOVABLE_INS));3061#endif /* MIPS III */30623063FAIL_IF(push_inst(compiler, CVT_S_S | flags | (4 << 21) | 1 | FS(TMP_FREG1) | FD(dst_r), MOVABLE_INS));30643065#if (!defined SLJIT_MIPS_REV || SLJIT_MIPS_REV <= 1)3066FAIL_IF(push_inst(compiler, BGEZ | S(src) | 5, UNMOVABLE_INS));3067#else /* SLJIT_MIPS_REV >= 1 */3068FAIL_IF(push_inst(compiler, BGEZ | S(src) | 4, UNMOVABLE_INS));3069#endif /* SLJIT_MIPS_REV < 1 */30703071FAIL_IF(push_inst(compiler, LUI | T(TMP_REG2) | IMM(0x41e0), UNMOVABLE_INS));3072FAIL_IF(push_inst(compiler, MTC1 | TA(0) | FS(TMP_FREG2), UNMOVABLE_INS));3073switch (cpu_feature_list & CPU_FEATURE_FR) {3074#if defined(SLJIT_MIPS_REV) && SLJIT_MIPS_REV >= 23075case CPU_FEATURE_FR:3076FAIL_IF(push_inst(compiler, MTHC1 | T(TMP_REG2) | FS(TMP_FREG2), UNMOVABLE_INS));3077break;3078#endif /* SLJIT_MIPS_REV >= 2 */3079default:3080FAIL_IF(push_inst(compiler, MTC1 | T(TMP_REG2) | FS(TMP_FREG2) | (1 << 11), UNMOVABLE_INS));3081#if !defined(SLJIT_MIPS_REV) || SLJIT_MIPS_REV <= 13082FAIL_IF(push_inst(compiler, NOP, UNMOVABLE_INS));3083#endif /* MIPS III */3084break;3085}3086FAIL_IF(push_inst(compiler, ADD_S | FMT(op) | FT(TMP_FREG2) | FS(dst_r) | FD(dst_r), UNMOVABLE_INS));30873088if (dst & SLJIT_MEM)3089return emit_op_mem2(compiler, FLOAT_DATA(op), FR(TMP_FREG1), dst, dstw, 0, 0);3090return SLJIT_SUCCESS;3091}3092#endif /* SLJIT_CONFIG_MIPS_64 */30933094#if (!defined SLJIT_MIPS_REV || SLJIT_MIPS_REV <= 1)3095FAIL_IF(push_inst(compiler, BLTZ | S(src) | 5, UNMOVABLE_INS));3096#else /* SLJIT_MIPS_REV >= 1 */3097FAIL_IF(push_inst(compiler, BLTZ | S(src) | 4, UNMOVABLE_INS));3098#endif /* SLJIT_MIPS_REV < 1 */3099FAIL_IF(push_inst(compiler, ANDI | S(src) | T(TMP_REG2) | IMM(1), DR(TMP_REG2)));31003101FAIL_IF(push_inst(compiler, MTC1 | flags | T(src) | FS(TMP_FREG1), MOVABLE_INS));3102#if !defined(SLJIT_MIPS_REV)3103FAIL_IF(push_inst(compiler, NOP, UNMOVABLE_INS));3104#endif /* !SLJIT_MIPS_REV */31053106FAIL_IF(push_inst(compiler, CVT_S_S | flags | (4 << 21) | ((~(sljit_ins)op & SLJIT_32) >> 8) | FS(TMP_FREG1) | FD(dst_r), MOVABLE_INS));31073108#if (!defined SLJIT_MIPS_REV || SLJIT_MIPS_REV <= 1)3109FAIL_IF(push_inst(compiler, BEQ | 6, UNMOVABLE_INS));3110#else /* SLJIT_MIPS_REV >= 1 */3111FAIL_IF(push_inst(compiler, BEQ | 5, UNMOVABLE_INS));3112#endif /* SLJIT_MIPS_REV < 1 */31133114#if (defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64)3115FAIL_IF(push_inst(compiler, DSRL | T(src) | D(TMP_REG1) | SH_IMM(1), DR(TMP_REG1)));3116#else /* !SLJIT_CONFIG_MIPS_64 */3117FAIL_IF(push_inst(compiler, SRL | T(src) | D(TMP_REG1) | SH_IMM(1), DR(TMP_REG1)));3118#endif /* SLJIT_CONFIG_MIPS_64 */31193120FAIL_IF(push_inst(compiler, OR | S(TMP_REG1) | T(TMP_REG2) | D(TMP_REG1), DR(TMP_REG1)));31213122FAIL_IF(push_inst(compiler, MTC1 | flags | T(TMP_REG1) | FS(TMP_FREG1), MOVABLE_INS));3123#if !defined(SLJIT_MIPS_REV)3124FAIL_IF(push_inst(compiler, NOP, UNMOVABLE_INS));3125#endif /* !SLJIT_MIPS_REV */31263127FAIL_IF(push_inst(compiler, CVT_S_S | flags | (4 << 21) | ((~(sljit_ins)op & SLJIT_32) >> 8) | FS(TMP_FREG1) | FD(dst_r), MOVABLE_INS));3128FAIL_IF(push_inst(compiler, ADD_S | FMT(op) | FT(dst_r) | FS(dst_r) | FD(dst_r), UNMOVABLE_INS));31293130if (dst & SLJIT_MEM)3131return emit_op_mem2(compiler, FLOAT_DATA(op), FR(TMP_FREG1), dst, dstw, 0, 0);3132return SLJIT_SUCCESS;3133}31343135static SLJIT_INLINE sljit_s32 sljit_emit_fop1_cmp(struct sljit_compiler *compiler, sljit_s32 op,3136sljit_s32 src1, sljit_sw src1w,3137sljit_s32 src2, sljit_sw src2w)3138{3139sljit_ins inst;31403141if (src1 & SLJIT_MEM) {3142FAIL_IF(emit_op_mem2(compiler, FLOAT_DATA(op) | LOAD_DATA, FR(TMP_FREG1), src1, src1w, src2, src2w));3143src1 = TMP_FREG1;3144}31453146if (src2 & SLJIT_MEM) {3147FAIL_IF(emit_op_mem2(compiler, FLOAT_DATA(op) | LOAD_DATA, FR(TMP_FREG2), src2, src2w, 0, 0));3148src2 = TMP_FREG2;3149}31503151switch (GET_FLAG_TYPE(op)) {3152case SLJIT_F_EQUAL:3153case SLJIT_ORDERED_EQUAL:3154inst = C_EQ_S;3155break;3156case SLJIT_F_NOT_EQUAL:3157case SLJIT_UNORDERED_OR_EQUAL:3158inst = C_UEQ_S;3159break;3160case SLJIT_F_LESS:3161case SLJIT_ORDERED_LESS:3162inst = C_OLT_S;3163break;3164case SLJIT_F_GREATER_EQUAL:3165case SLJIT_UNORDERED_OR_LESS:3166inst = C_ULT_S;3167break;3168case SLJIT_F_GREATER:3169case SLJIT_ORDERED_GREATER:3170inst = C_ULE_S;3171break;3172case SLJIT_F_LESS_EQUAL:3173case SLJIT_UNORDERED_OR_GREATER:3174inst = C_OLE_S;3175break;3176default:3177SLJIT_ASSERT(GET_FLAG_TYPE(op) == SLJIT_UNORDERED);3178inst = C_UN_S;3179break;3180}3181return push_inst(compiler, inst | FMT(op) | FT(src2) | FS(src1) | C_FD, UNMOVABLE_INS);3182}31833184SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fop1(struct sljit_compiler *compiler, sljit_s32 op,3185sljit_s32 dst, sljit_sw dstw,3186sljit_s32 src, sljit_sw srcw)3187{3188sljit_s32 dst_r;31893190CHECK_ERROR();3191compiler->cache_arg = 0;3192compiler->cache_argw = 0;31933194SLJIT_COMPILE_ASSERT((SLJIT_32 == 0x100) && !(DOUBLE_DATA & 0x2), float_transfer_bit_error);3195SELECT_FOP1_OPERATION_WITH_CHECKS(compiler, op, dst, dstw, src, srcw);31963197if (GET_OPCODE(op) == SLJIT_CONV_F64_FROM_F32)3198op ^= SLJIT_32;31993200dst_r = FAST_IS_REG(dst) ? dst : TMP_FREG1;32013202if (src & SLJIT_MEM) {3203FAIL_IF(emit_op_mem2(compiler, FLOAT_DATA(op) | LOAD_DATA, FR(dst_r), src, srcw, dst, dstw));3204src = dst_r;3205}32063207switch (GET_OPCODE(op)) {3208case SLJIT_MOV_F64:3209if (src != dst_r) {3210if (!(dst & SLJIT_MEM))3211FAIL_IF(push_inst(compiler, MOV_fmt(FMT(op)) | FS(src) | FD(dst_r), MOVABLE_INS));3212else3213dst_r = src;3214}3215break;3216case SLJIT_NEG_F64:3217FAIL_IF(push_inst(compiler, NEG_S | FMT(op) | FS(src) | FD(dst_r), MOVABLE_INS));3218break;3219case SLJIT_ABS_F64:3220FAIL_IF(push_inst(compiler, ABS_S | FMT(op) | FS(src) | FD(dst_r), MOVABLE_INS));3221break;3222case SLJIT_CONV_F64_FROM_F32:3223/* The SLJIT_32 bit is inverted because sljit_f32 needs to be loaded from the memory. */3224FAIL_IF(push_inst(compiler, CVT_S_S | (sljit_ins)((op & SLJIT_32) ? 1 : (1 << 21)) | FS(src) | FD(dst_r), MOVABLE_INS));3225op ^= SLJIT_32;3226break;3227}32283229if (dst & SLJIT_MEM)3230return emit_op_mem2(compiler, FLOAT_DATA(op), FR(dst_r), dst, dstw, 0, 0);3231return SLJIT_SUCCESS;3232}32333234SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fop2(struct sljit_compiler *compiler, sljit_s32 op,3235sljit_s32 dst, sljit_sw dstw,3236sljit_s32 src1, sljit_sw src1w,3237sljit_s32 src2, sljit_sw src2w)3238{3239sljit_s32 dst_r, flags = 0;32403241CHECK_ERROR();3242CHECK(check_sljit_emit_fop2(compiler, op, dst, dstw, src1, src1w, src2, src2w));3243ADJUST_LOCAL_OFFSET(dst, dstw);3244ADJUST_LOCAL_OFFSET(src1, src1w);3245ADJUST_LOCAL_OFFSET(src2, src2w);32463247compiler->cache_arg = 0;3248compiler->cache_argw = 0;32493250dst_r = FAST_IS_REG(dst) ? dst : TMP_FREG2;32513252if (src1 & SLJIT_MEM) {3253if (getput_arg_fast(compiler, FLOAT_DATA(op) | LOAD_DATA, FR(TMP_FREG1), src1, src1w)) {3254FAIL_IF(compiler->error);3255src1 = TMP_FREG1;3256} else3257flags |= SLOW_SRC1;3258}32593260if (src2 & SLJIT_MEM) {3261if (getput_arg_fast(compiler, FLOAT_DATA(op) | LOAD_DATA, FR(TMP_FREG2), src2, src2w)) {3262FAIL_IF(compiler->error);3263src2 = TMP_FREG2;3264} else3265flags |= SLOW_SRC2;3266}32673268if ((flags & (SLOW_SRC1 | SLOW_SRC2)) == (SLOW_SRC1 | SLOW_SRC2)) {3269if ((dst & SLJIT_MEM) && !can_cache(src1, src1w, src2, src2w) && can_cache(src1, src1w, dst, dstw)) {3270FAIL_IF(getput_arg(compiler, FLOAT_DATA(op) | LOAD_DATA, FR(TMP_FREG2), src2, src2w, src1, src1w));3271FAIL_IF(getput_arg(compiler, FLOAT_DATA(op) | LOAD_DATA, FR(TMP_FREG1), src1, src1w, dst, dstw));3272} else {3273FAIL_IF(getput_arg(compiler, FLOAT_DATA(op) | LOAD_DATA, FR(TMP_FREG1), src1, src1w, src2, src2w));3274FAIL_IF(getput_arg(compiler, FLOAT_DATA(op) | LOAD_DATA, FR(TMP_FREG2), src2, src2w, dst, dstw));3275}3276}3277else if (flags & SLOW_SRC1)3278FAIL_IF(getput_arg(compiler, FLOAT_DATA(op) | LOAD_DATA, FR(TMP_FREG1), src1, src1w, dst, dstw));3279else if (flags & SLOW_SRC2)3280FAIL_IF(getput_arg(compiler, FLOAT_DATA(op) | LOAD_DATA, FR(TMP_FREG2), src2, src2w, dst, dstw));32813282if (flags & SLOW_SRC1)3283src1 = TMP_FREG1;3284if (flags & SLOW_SRC2)3285src2 = TMP_FREG2;32863287switch (GET_OPCODE(op)) {3288case SLJIT_ADD_F64:3289FAIL_IF(push_inst(compiler, ADD_S | FMT(op) | FT(src2) | FS(src1) | FD(dst_r), MOVABLE_INS));3290break;3291case SLJIT_SUB_F64:3292FAIL_IF(push_inst(compiler, SUB_S | FMT(op) | FT(src2) | FS(src1) | FD(dst_r), MOVABLE_INS));3293break;3294case SLJIT_MUL_F64:3295FAIL_IF(push_inst(compiler, MUL_S | FMT(op) | FT(src2) | FS(src1) | FD(dst_r), MOVABLE_INS));3296break;3297case SLJIT_DIV_F64:3298FAIL_IF(push_inst(compiler, DIV_S | FMT(op) | FT(src2) | FS(src1) | FD(dst_r), MOVABLE_INS));3299break;3300case SLJIT_COPYSIGN_F64:3301return emit_copysign(compiler, op, src1, src2, dst_r);3302}33033304if (dst_r == TMP_FREG2)3305FAIL_IF(emit_op_mem2(compiler, FLOAT_DATA(op), FR(TMP_FREG2), dst, dstw, 0, 0));33063307return SLJIT_SUCCESS;3308}33093310SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fset32(struct sljit_compiler *compiler,3311sljit_s32 freg, sljit_f32 value)3312{3313union {3314sljit_s32 imm;3315sljit_f32 value;3316} u;33173318CHECK_ERROR();3319CHECK(check_sljit_emit_fset32(compiler, freg, value));33203321u.value = value;33223323if (u.imm == 0)3324return push_inst(compiler, MTC1 | TA(0) | FS(freg), MOVABLE_INS);33253326FAIL_IF(load_immediate(compiler, DR(TMP_REG1), u.imm));3327return push_inst(compiler, MTC1 | T(TMP_REG1) | FS(freg), MOVABLE_INS);3328}33293330/* --------------------------------------------------------------------- */3331/* Conditional instructions */3332/* --------------------------------------------------------------------- */33333334SLJIT_API_FUNC_ATTRIBUTE struct sljit_label* sljit_emit_label(struct sljit_compiler *compiler)3335{3336struct sljit_label *label;33373338CHECK_ERROR_PTR();3339CHECK_PTR(check_sljit_emit_label(compiler));33403341if (compiler->last_label && compiler->last_label->size == compiler->size)3342return compiler->last_label;33433344label = (struct sljit_label*)ensure_abuf(compiler, sizeof(struct sljit_label));3345PTR_FAIL_IF(!label);3346set_label(label, compiler);3347compiler->delay_slot = UNMOVABLE_INS;3348return label;3349}33503351SLJIT_API_FUNC_ATTRIBUTE struct sljit_label* sljit_emit_aligned_label(struct sljit_compiler *compiler,3352sljit_s32 alignment, struct sljit_read_only_buffer *buffers)3353{3354sljit_uw mask, i;3355struct sljit_label *label;3356struct sljit_label *next_label;3357struct sljit_extended_label *ext_label;33583359CHECK_ERROR_PTR();3360CHECK_PTR(check_sljit_emit_aligned_label(compiler, alignment, buffers));33613362sljit_reset_read_only_buffers(buffers);33633364if (alignment <= SLJIT_LABEL_ALIGN_4) {3365SLJIT_SKIP_CHECKS(compiler);3366label = sljit_emit_label(compiler);3367PTR_FAIL_IF(!label);3368} else {3369/* The used space is filled with NOPs. */3370mask = ((sljit_uw)1 << alignment) - sizeof(sljit_ins);33713372for (i = (mask >> 2); i != 0; i--)3373PTR_FAIL_IF(push_inst(compiler, NOP, UNMOVABLE_INS));33743375ext_label = (struct sljit_extended_label*)ensure_abuf(compiler, sizeof(struct sljit_extended_label));3376PTR_FAIL_IF(!ext_label);3377set_extended_label(ext_label, compiler, SLJIT_LABEL_ALIGNED, mask);3378label = &ext_label->label;3379}33803381if (buffers == NULL)3382return label;33833384next_label = label;33853386while (1) {3387buffers->u.label = next_label;33883389for (i = (buffers->size + 3) >> 2; i > 0; i--)3390PTR_FAIL_IF(push_inst(compiler, NOP, UNMOVABLE_INS));33913392buffers = buffers->next;33933394if (buffers == NULL)3395break;33963397SLJIT_SKIP_CHECKS(compiler);3398next_label = sljit_emit_label(compiler);3399PTR_FAIL_IF(!next_label);3400}34013402return label;3403}34043405#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)3406#define BRANCH_LENGTH 43407#else3408#define BRANCH_LENGTH 83409#endif34103411#define BR_Z(src) \3412inst = BEQ | SA(src) | TA(0) | BRANCH_LENGTH; \3413flags = IS_BIT26_COND; \3414delay_check = src;34153416#define BR_NZ(src) \3417inst = BNE | SA(src) | TA(0) | BRANCH_LENGTH; \3418flags = IS_BIT26_COND; \3419delay_check = src;34203421#if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 6)34223423#define BR_T() \3424inst = BC1NEZ; \3425flags = IS_BIT23_COND; \3426delay_check = FCSR_FCC;3427#define BR_F() \3428inst = BC1EQZ; \3429flags = IS_BIT23_COND; \3430delay_check = FCSR_FCC;34313432#else /* SLJIT_MIPS_REV < 6 */34333434#define BR_T() \3435inst = BC1T | BRANCH_LENGTH; \3436flags = IS_BIT16_COND; \3437delay_check = FCSR_FCC;3438#define BR_F() \3439inst = BC1F | BRANCH_LENGTH; \3440flags = IS_BIT16_COND; \3441delay_check = FCSR_FCC;34423443#endif /* SLJIT_MIPS_REV >= 6 */34443445SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_jump(struct sljit_compiler *compiler, sljit_s32 type)3446{3447struct sljit_jump *jump;3448sljit_ins inst;3449sljit_u32 flags = 0;3450sljit_s32 delay_check = UNMOVABLE_INS;34513452CHECK_ERROR_PTR();3453CHECK_PTR(check_sljit_emit_jump(compiler, type));34543455jump = (struct sljit_jump*)ensure_abuf(compiler, sizeof(struct sljit_jump));3456PTR_FAIL_IF(!jump);3457set_jump(jump, compiler, type & SLJIT_REWRITABLE_JUMP);3458type &= 0xff;34593460switch (type) {3461case SLJIT_EQUAL:3462BR_NZ(EQUAL_FLAG);3463break;3464case SLJIT_NOT_EQUAL:3465BR_Z(EQUAL_FLAG);3466break;3467case SLJIT_LESS:3468case SLJIT_GREATER:3469case SLJIT_SIG_LESS:3470case SLJIT_SIG_GREATER:3471case SLJIT_OVERFLOW:3472case SLJIT_CARRY:3473case SLJIT_ATOMIC_STORED:3474BR_Z(OTHER_FLAG);3475break;3476case SLJIT_GREATER_EQUAL:3477case SLJIT_LESS_EQUAL:3478case SLJIT_SIG_GREATER_EQUAL:3479case SLJIT_SIG_LESS_EQUAL:3480case SLJIT_NOT_OVERFLOW:3481case SLJIT_NOT_CARRY:3482case SLJIT_ATOMIC_NOT_STORED:3483BR_NZ(OTHER_FLAG);3484break;3485case SLJIT_F_NOT_EQUAL:3486case SLJIT_F_GREATER_EQUAL:3487case SLJIT_F_GREATER:3488case SLJIT_UNORDERED_OR_NOT_EQUAL:3489case SLJIT_ORDERED_NOT_EQUAL:3490case SLJIT_UNORDERED_OR_GREATER_EQUAL:3491case SLJIT_ORDERED_GREATER_EQUAL:3492case SLJIT_ORDERED_GREATER:3493case SLJIT_UNORDERED_OR_GREATER:3494case SLJIT_ORDERED:3495BR_T();3496break;3497case SLJIT_F_EQUAL:3498case SLJIT_F_LESS:3499case SLJIT_F_LESS_EQUAL:3500case SLJIT_ORDERED_EQUAL:3501case SLJIT_UNORDERED_OR_EQUAL:3502case SLJIT_ORDERED_LESS:3503case SLJIT_UNORDERED_OR_LESS:3504case SLJIT_UNORDERED_OR_LESS_EQUAL:3505case SLJIT_ORDERED_LESS_EQUAL:3506case SLJIT_UNORDERED:3507BR_F();3508break;3509default:3510/* Not conditional branch. */3511inst = 0;3512break;3513}35143515jump->flags |= flags;3516if (compiler->delay_slot == MOVABLE_INS || (compiler->delay_slot != UNMOVABLE_INS && compiler->delay_slot != delay_check))3517jump->flags |= IS_MOVABLE;35183519if (inst)3520PTR_FAIL_IF(push_inst(compiler, inst, UNMOVABLE_INS));35213522if (type <= SLJIT_JUMP)3523PTR_FAIL_IF(push_inst(compiler, JR | S(PIC_ADDR_REG), UNMOVABLE_INS));3524else {3525jump->flags |= IS_JAL;3526PTR_FAIL_IF(push_inst(compiler, JALR | S(PIC_ADDR_REG) | DA(RETURN_ADDR_REG), UNMOVABLE_INS));3527}35283529jump->addr = compiler->size;3530PTR_FAIL_IF(push_inst(compiler, NOP, UNMOVABLE_INS));35313532/* Maximum number of instructions required for generating a constant. */3533#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)3534compiler->size += 2;3535#else3536compiler->size += 6;3537#endif3538return jump;3539}35403541#define RESOLVE_IMM1() \3542if (src1 == SLJIT_IMM) { \3543if (src1w) { \3544PTR_FAIL_IF(load_immediate(compiler, DR(TMP_REG1), src1w)); \3545src1 = TMP_REG1; \3546} \3547else \3548src1 = 0; \3549}35503551#define RESOLVE_IMM2() \3552if (src2 == SLJIT_IMM) { \3553if (src2w) { \3554PTR_FAIL_IF(load_immediate(compiler, DR(src2_tmp_reg), src2w)); \3555src2 = src2_tmp_reg; \3556} \3557else \3558src2 = 0; \3559}35603561SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_cmp(struct sljit_compiler *compiler, sljit_s32 type,3562sljit_s32 src1, sljit_sw src1w,3563sljit_s32 src2, sljit_sw src2w)3564{3565struct sljit_jump *jump;3566sljit_s32 flags;3567sljit_ins inst;3568sljit_s32 src2_tmp_reg = FAST_IS_REG(src1) ? TMP_REG1 : TMP_REG2;35693570CHECK_ERROR_PTR();3571CHECK_PTR(check_sljit_emit_cmp(compiler, type, src1, src1w, src2, src2w));3572ADJUST_LOCAL_OFFSET(src1, src1w);3573ADJUST_LOCAL_OFFSET(src2, src2w);35743575compiler->cache_arg = 0;3576compiler->cache_argw = 0;3577#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)3578flags = WORD_DATA | LOAD_DATA;3579#else /* !SLJIT_CONFIG_MIPS_32 */3580flags = ((type & SLJIT_32) ? INT_DATA : WORD_DATA) | LOAD_DATA;3581#endif /* SLJIT_CONFIG_MIPS_32 */35823583if (src1 & SLJIT_MEM) {3584PTR_FAIL_IF(emit_op_mem2(compiler, flags, DR(TMP_REG1), src1, src1w, src2, src2w));3585src1 = TMP_REG1;3586}35873588if (src2 & SLJIT_MEM) {3589PTR_FAIL_IF(emit_op_mem2(compiler, flags, DR(src2_tmp_reg), src2, src2w, 0, 0));3590src2 = src2_tmp_reg;3591}35923593jump = (struct sljit_jump*)ensure_abuf(compiler, sizeof(struct sljit_jump));3594PTR_FAIL_IF(!jump);3595set_jump(jump, compiler, type & SLJIT_REWRITABLE_JUMP);3596type &= 0xff;35973598if (type <= SLJIT_NOT_EQUAL) {3599RESOLVE_IMM1();3600RESOLVE_IMM2();3601jump->flags |= IS_BIT26_COND;3602if (compiler->delay_slot == MOVABLE_INS || (compiler->delay_slot != UNMOVABLE_INS && compiler->delay_slot != DR(src1) && compiler->delay_slot != DR(src2)))3603jump->flags |= IS_MOVABLE;3604PTR_FAIL_IF(push_inst(compiler, (type == SLJIT_EQUAL ? BNE : BEQ) | S(src1) | T(src2) | BRANCH_LENGTH, UNMOVABLE_INS));3605} else if (type >= SLJIT_SIG_LESS && ((src1 == SLJIT_IMM && src1w == 0) || (src2 == SLJIT_IMM && src2w == 0))) {3606inst = NOP;3607if (src1 == SLJIT_IMM && src1w == 0) {3608RESOLVE_IMM2();3609switch (type) {3610case SLJIT_SIG_LESS:3611inst = BLEZ;3612jump->flags |= IS_BIT26_COND;3613break;3614case SLJIT_SIG_GREATER_EQUAL:3615inst = BGTZ;3616jump->flags |= IS_BIT26_COND;3617break;3618case SLJIT_SIG_GREATER:3619inst = BGEZ;3620jump->flags |= IS_BIT16_COND;3621break;3622case SLJIT_SIG_LESS_EQUAL:3623inst = BLTZ;3624jump->flags |= IS_BIT16_COND;3625break;3626}3627src1 = src2;3628}3629else {3630RESOLVE_IMM1();3631switch (type) {3632case SLJIT_SIG_LESS:3633inst = BGEZ;3634jump->flags |= IS_BIT16_COND;3635break;3636case SLJIT_SIG_GREATER_EQUAL:3637inst = BLTZ;3638jump->flags |= IS_BIT16_COND;3639break;3640case SLJIT_SIG_GREATER:3641inst = BLEZ;3642jump->flags |= IS_BIT26_COND;3643break;3644case SLJIT_SIG_LESS_EQUAL:3645inst = BGTZ;3646jump->flags |= IS_BIT26_COND;3647break;3648}3649}3650PTR_FAIL_IF(push_inst(compiler, inst | S(src1) | BRANCH_LENGTH, UNMOVABLE_INS));3651}3652else {3653if (type == SLJIT_LESS || type == SLJIT_GREATER_EQUAL || type == SLJIT_SIG_LESS || type == SLJIT_SIG_GREATER_EQUAL) {3654RESOLVE_IMM1();3655if (src2 == SLJIT_IMM && src2w <= SIMM_MAX && src2w >= SIMM_MIN)3656PTR_FAIL_IF(push_inst(compiler, (type <= SLJIT_LESS_EQUAL ? SLTIU : SLTI) | S(src1) | T(TMP_REG1) | IMM(src2w), DR(TMP_REG1)));3657else {3658RESOLVE_IMM2();3659PTR_FAIL_IF(push_inst(compiler, (type <= SLJIT_LESS_EQUAL ? SLTU : SLT) | S(src1) | T(src2) | D(TMP_REG1), DR(TMP_REG1)));3660}3661type = (type == SLJIT_LESS || type == SLJIT_SIG_LESS) ? SLJIT_NOT_EQUAL : SLJIT_EQUAL;3662}3663else {3664RESOLVE_IMM2();3665if (src1 == SLJIT_IMM && src1w <= SIMM_MAX && src1w >= SIMM_MIN)3666PTR_FAIL_IF(push_inst(compiler, (type <= SLJIT_LESS_EQUAL ? SLTIU : SLTI) | S(src2) | T(TMP_REG1) | IMM(src1w), DR(TMP_REG1)));3667else {3668RESOLVE_IMM1();3669PTR_FAIL_IF(push_inst(compiler, (type <= SLJIT_LESS_EQUAL ? SLTU : SLT) | S(src2) | T(src1) | D(TMP_REG1), DR(TMP_REG1)));3670}3671type = (type == SLJIT_GREATER || type == SLJIT_SIG_GREATER) ? SLJIT_NOT_EQUAL : SLJIT_EQUAL;3672}36733674jump->flags |= IS_BIT26_COND;3675PTR_FAIL_IF(push_inst(compiler, (type == SLJIT_EQUAL ? BNE : BEQ) | S(TMP_REG1) | TA(0) | BRANCH_LENGTH, UNMOVABLE_INS));3676}36773678PTR_FAIL_IF(push_inst(compiler, JR | S(PIC_ADDR_REG), UNMOVABLE_INS));3679jump->addr = compiler->size;3680PTR_FAIL_IF(push_inst(compiler, NOP, UNMOVABLE_INS));36813682/* Maximum number of instructions required for generating a constant. */3683#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)3684compiler->size += 2;3685#else3686compiler->size += 6;3687#endif3688return jump;3689}36903691#undef RESOLVE_IMM13692#undef RESOLVE_IMM236933694#undef BRANCH_LENGTH3695#undef BR_Z3696#undef BR_NZ3697#undef BR_T3698#undef BR_F36993700SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_ijump(struct sljit_compiler *compiler, sljit_s32 type, sljit_s32 src, sljit_sw srcw)3701{3702struct sljit_jump *jump = NULL;37033704CHECK_ERROR();3705CHECK(check_sljit_emit_ijump(compiler, type, src, srcw));37063707if (src == SLJIT_IMM) {3708jump = (struct sljit_jump*)ensure_abuf(compiler, sizeof(struct sljit_jump));3709FAIL_IF(!jump);3710set_jump(jump, compiler, JUMP_ADDR | ((type >= SLJIT_FAST_CALL) ? IS_JAL : 0));3711jump->u.target = (sljit_uw)srcw;37123713if (compiler->delay_slot != UNMOVABLE_INS)3714jump->flags |= IS_MOVABLE;37153716src = PIC_ADDR_REG;3717} else if (src & SLJIT_MEM) {3718ADJUST_LOCAL_OFFSET(src, srcw);3719FAIL_IF(emit_op_mem(compiler, WORD_DATA | LOAD_DATA, DR(PIC_ADDR_REG), src, srcw));3720src = PIC_ADDR_REG;3721}37223723if (type <= SLJIT_JUMP)3724FAIL_IF(push_inst(compiler, JR | S(src), UNMOVABLE_INS));3725else3726FAIL_IF(push_inst(compiler, JALR | S(src) | DA(RETURN_ADDR_REG), UNMOVABLE_INS));37273728if (jump != NULL) {3729jump->addr = compiler->size;37303731/* Maximum number of instructions required for generating a constant. */3732#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)3733compiler->size += 2;3734#else3735compiler->size += 6;3736#endif3737}37383739return push_inst(compiler, NOP, UNMOVABLE_INS);3740}37413742SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_flags(struct sljit_compiler *compiler, sljit_s32 op,3743sljit_s32 dst, sljit_sw dstw,3744sljit_s32 type)3745{3746sljit_s32 src_ar, dst_ar, invert;3747sljit_s32 saved_op = op;3748#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)3749sljit_s32 mem_type = WORD_DATA;3750#else3751sljit_s32 mem_type = ((op & SLJIT_32) || op == SLJIT_MOV32) ? (INT_DATA | SIGNED_DATA) : WORD_DATA;3752#endif37533754CHECK_ERROR();3755CHECK(check_sljit_emit_op_flags(compiler, op, dst, dstw, type));3756ADJUST_LOCAL_OFFSET(dst, dstw);37573758op = GET_OPCODE(op);3759dst_ar = DR((op < SLJIT_ADD && FAST_IS_REG(dst)) ? dst : TMP_REG2);37603761compiler->cache_arg = 0;3762compiler->cache_argw = 0;37633764if (op >= SLJIT_ADD && (dst & SLJIT_MEM))3765FAIL_IF(emit_op_mem2(compiler, mem_type | LOAD_DATA, DR(TMP_REG1), dst, dstw, dst, dstw));37663767if (type < SLJIT_F_EQUAL) {3768src_ar = OTHER_FLAG;3769invert = type & 0x1;37703771switch (type) {3772case SLJIT_EQUAL:3773case SLJIT_NOT_EQUAL:3774FAIL_IF(push_inst(compiler, SLTIU | SA(EQUAL_FLAG) | TA(dst_ar) | IMM(1), dst_ar));3775src_ar = dst_ar;3776break;3777case SLJIT_OVERFLOW:3778case SLJIT_NOT_OVERFLOW:3779if (compiler->status_flags_state & (SLJIT_CURRENT_FLAGS_ADD | SLJIT_CURRENT_FLAGS_SUB)) {3780src_ar = OTHER_FLAG;3781break;3782}3783FAIL_IF(push_inst(compiler, SLTIU | SA(OTHER_FLAG) | TA(dst_ar) | IMM(1), dst_ar));3784src_ar = dst_ar;3785invert ^= 0x1;3786break;3787}3788} else {3789invert = 0;37903791switch (type) {3792case SLJIT_F_NOT_EQUAL:3793case SLJIT_F_GREATER_EQUAL:3794case SLJIT_F_GREATER:3795case SLJIT_UNORDERED_OR_NOT_EQUAL:3796case SLJIT_ORDERED_NOT_EQUAL:3797case SLJIT_UNORDERED_OR_GREATER_EQUAL:3798case SLJIT_ORDERED_GREATER_EQUAL:3799case SLJIT_ORDERED_GREATER:3800case SLJIT_UNORDERED_OR_GREATER:3801case SLJIT_ORDERED:3802invert = 1;3803break;3804}38053806#if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 6)3807FAIL_IF(push_inst(compiler, MFC1 | TA(dst_ar) | FS(TMP_FREG3), dst_ar));3808#else /* SLJIT_MIPS_REV < 6 */3809FAIL_IF(push_inst(compiler, CFC1 | TA(dst_ar) | DA(FCSR_REG), dst_ar));3810#endif /* SLJIT_MIPS_REV >= 6 */3811FAIL_IF(push_inst(compiler, SRL | TA(dst_ar) | DA(dst_ar) | SH_IMM(23), dst_ar));3812FAIL_IF(push_inst(compiler, ANDI | SA(dst_ar) | TA(dst_ar) | IMM(1), dst_ar));3813src_ar = dst_ar;3814}38153816if (invert) {3817FAIL_IF(push_inst(compiler, XORI | SA(src_ar) | TA(dst_ar) | IMM(1), dst_ar));3818src_ar = dst_ar;3819}38203821if (op < SLJIT_ADD) {3822if (dst & SLJIT_MEM)3823return emit_op_mem(compiler, mem_type, src_ar, dst, dstw);38243825if (src_ar != dst_ar)3826return push_inst(compiler, ADDU_W | SA(src_ar) | TA(0) | DA(dst_ar), dst_ar);3827return SLJIT_SUCCESS;3828}38293830/* OTHER_FLAG cannot be specified as src2 argument at the moment. */3831if (DR(TMP_REG2) != src_ar)3832FAIL_IF(push_inst(compiler, ADDU_W | SA(src_ar) | TA(0) | D(TMP_REG2), DR(TMP_REG2)));38333834mem_type |= CUMULATIVE_OP | LOGICAL_OP | IMM_OP | ALT_KEEP_CACHE;38353836if (dst & SLJIT_MEM)3837return emit_op(compiler, saved_op, mem_type, dst, dstw, TMP_REG1, 0, TMP_REG2, 0);3838return emit_op(compiler, saved_op, mem_type, dst, dstw, dst, dstw, TMP_REG2, 0);3839}38403841#if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 1 && SLJIT_MIPS_REV < 6)38423843static sljit_ins get_select_cc(sljit_s32 type, sljit_s32 is_float)3844{3845switch (type) {3846case SLJIT_EQUAL:3847return (is_float ? MOVZ_S : MOVZ) | TA(EQUAL_FLAG);3848case SLJIT_NOT_EQUAL:3849return (is_float ? MOVN_S : MOVN) | TA(EQUAL_FLAG);3850case SLJIT_LESS:3851case SLJIT_GREATER:3852case SLJIT_SIG_LESS:3853case SLJIT_SIG_GREATER:3854case SLJIT_OVERFLOW:3855case SLJIT_CARRY:3856return (is_float ? MOVN_S : MOVN) | TA(OTHER_FLAG);3857case SLJIT_GREATER_EQUAL:3858case SLJIT_LESS_EQUAL:3859case SLJIT_SIG_GREATER_EQUAL:3860case SLJIT_SIG_LESS_EQUAL:3861case SLJIT_NOT_OVERFLOW:3862case SLJIT_NOT_CARRY:3863return (is_float ? MOVZ_S : MOVZ) | TA(OTHER_FLAG);3864case SLJIT_F_EQUAL:3865case SLJIT_F_LESS:3866case SLJIT_F_LESS_EQUAL:3867case SLJIT_ORDERED_EQUAL:3868case SLJIT_UNORDERED_OR_EQUAL:3869case SLJIT_ORDERED_LESS:3870case SLJIT_UNORDERED_OR_LESS:3871case SLJIT_UNORDERED_OR_LESS_EQUAL:3872case SLJIT_ORDERED_LESS_EQUAL:3873case SLJIT_UNORDERED:3874return is_float ? MOVT_S : MOVT;3875case SLJIT_F_NOT_EQUAL:3876case SLJIT_F_GREATER_EQUAL:3877case SLJIT_F_GREATER:3878case SLJIT_UNORDERED_OR_NOT_EQUAL:3879case SLJIT_ORDERED_NOT_EQUAL:3880case SLJIT_UNORDERED_OR_GREATER_EQUAL:3881case SLJIT_ORDERED_GREATER_EQUAL:3882case SLJIT_ORDERED_GREATER:3883case SLJIT_UNORDERED_OR_GREATER:3884case SLJIT_ORDERED:3885return is_float ? MOVF_S : MOVF;3886default:3887SLJIT_UNREACHABLE();3888return (is_float ? MOVZ_S : MOVZ) | TA(OTHER_FLAG);3889}3890}38913892#endif /* SLJIT_MIPS_REV >= 1 */38933894SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_select(struct sljit_compiler *compiler, sljit_s32 type,3895sljit_s32 dst_reg,3896sljit_s32 src1, sljit_sw src1w,3897sljit_s32 src2_reg)3898{3899#if (defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64)3900sljit_s32 inp_flags = ((type & SLJIT_32) ? INT_DATA : WORD_DATA) | LOAD_DATA;3901sljit_ins mov_ins = (type & SLJIT_32) ? ADDU : DADDU;3902#else /* !SLJIT_CONFIG_MIPS_64 */3903sljit_s32 inp_flags = WORD_DATA | LOAD_DATA;3904sljit_ins mov_ins = ADDU;3905#endif /* SLJIT_CONFIG_MIPS_64 */39063907#if !(defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 1 && SLJIT_MIPS_REV < 6)3908struct sljit_label *label;3909struct sljit_jump *jump;3910#endif /* !(SLJIT_MIPS_REV >= 1 && SLJIT_MIPS_REV < 6) */39113912CHECK_ERROR();3913CHECK(check_sljit_emit_select(compiler, type, dst_reg, src1, src1w, src2_reg));3914ADJUST_LOCAL_OFFSET(src1, src1w);39153916#if (defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64)3917if (src1 == SLJIT_IMM && (type & SLJIT_32))3918src1w = (sljit_s32)src1w;3919#endif39203921type &= ~SLJIT_32;39223923if (type & SLJIT_COMPARE_SELECT) {3924type ^= SLJIT_COMPARE_SELECT;39253926if (src1 & SLJIT_MEM) {3927FAIL_IF(emit_op_mem(compiler, inp_flags, DR(TMP_REG1), src1, src1w));3928src1 = TMP_REG1;3929} else if (src1 == SLJIT_IMM) {3930if (src1w == 0) {3931src1 = 0;3932} else {3933FAIL_IF(load_immediate(compiler, DR(TMP_REG1), src1w));3934src1 = TMP_REG1;3935}3936}39373938src1w = 0;3939FAIL_IF(emit_op(compiler, SLJIT_SUB | SLJIT_SET(type & ~0x1), IMM_OP, 0, 0, src1, 0, src2_reg, 0));3940}39413942#if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 1 && SLJIT_MIPS_REV < 6)3943if (src1 & SLJIT_MEM) {3944FAIL_IF(emit_op_mem(compiler, inp_flags, DR(TMP_REG1), src1, src1w));3945src1 = TMP_REG1;3946} else if (src1 == SLJIT_IMM) {3947FAIL_IF(load_immediate(compiler, DR(TMP_REG1), src1w));3948src1 = TMP_REG1;3949}39503951if (dst_reg != src2_reg) {3952if (dst_reg == src1) {3953src1 = src2_reg;3954type ^= 0x1;3955} else3956FAIL_IF(push_inst(compiler, mov_ins | S(src2_reg) | TA(0) | D(dst_reg), DR(dst_reg)));3957}39583959return push_inst(compiler, get_select_cc(type, 0) | S(src1) | D(dst_reg), DR(dst_reg));39603961#else /* SLJIT_MIPS_REV < 1 || SLJIT_MIPS_REV >= 6 */3962if (dst_reg != src2_reg) {3963if (dst_reg == src1) {3964src1 = src2_reg;3965src1w = 0;3966type ^= 0x1;3967} else {3968if (ADDRESSING_DEPENDS_ON(src1, dst_reg)) {3969FAIL_IF(push_inst(compiler, ADDU_W | S(dst_reg) | TA(0) | D(TMP_REG1), DR(TMP_REG1)));39703971if ((src1 & REG_MASK) == dst_reg)3972src1 = (src1 & ~REG_MASK) | TMP_REG1;39733974if (OFFS_REG(src1) == dst_reg)3975src1 = (src1 & ~OFFS_REG_MASK) | TO_OFFS_REG(TMP_REG1);3976}39773978FAIL_IF(push_inst(compiler, mov_ins | S(src2_reg) | TA(0) | D(dst_reg), DR(dst_reg)));3979}3980}39813982SLJIT_SKIP_CHECKS(compiler);3983jump = sljit_emit_jump(compiler, type ^ 0x1);3984FAIL_IF(!jump);39853986if (src1 & SLJIT_MEM) {3987FAIL_IF(emit_op_mem(compiler, inp_flags, DR(dst_reg), src1, src1w));3988} else if (src1 == SLJIT_IMM) {3989FAIL_IF(load_immediate(compiler, DR(dst_reg), src1w));3990} else3991FAIL_IF(push_inst(compiler, mov_ins | S(src1) | TA(0) | D(dst_reg), DR(dst_reg)));39923993SLJIT_SKIP_CHECKS(compiler);3994label = sljit_emit_label(compiler);3995FAIL_IF(!label);39963997sljit_set_label(jump, label);3998return SLJIT_SUCCESS;3999#endif /* SLJIT_MIPS_REV >= 1 */4000}40014002SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fselect(struct sljit_compiler *compiler, sljit_s32 type,4003sljit_s32 dst_freg,4004sljit_s32 src1, sljit_sw src1w,4005sljit_s32 src2_freg)4006{4007#if !(defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 1 && SLJIT_MIPS_REV < 6)4008struct sljit_label *label;4009struct sljit_jump *jump;4010#endif /* !(SLJIT_MIPS_REV >= 1 && SLJIT_MIPS_REV < 6) */40114012CHECK_ERROR();4013CHECK(check_sljit_emit_fselect(compiler, type, dst_freg, src1, src1w, src2_freg));40144015ADJUST_LOCAL_OFFSET(src1, src1w);40164017if (dst_freg != src2_freg) {4018if (dst_freg == src1) {4019src1 = src2_freg;4020src1w = 0;4021type ^= 0x1;4022} else4023FAIL_IF(push_inst(compiler, MOV_fmt(FMT(type)) | FS(src2_freg) | FD(dst_freg), MOVABLE_INS));4024}40254026#if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 1 && SLJIT_MIPS_REV < 6)4027if (src1 & SLJIT_MEM) {4028FAIL_IF(emit_op_mem(compiler, FLOAT_DATA(type) | LOAD_DATA, FR(TMP_FREG2), src1, src1w));4029src1 = TMP_FREG2;4030}40314032return push_inst(compiler, get_select_cc(type & ~SLJIT_32, 1) | FMT(type) | FS(src1) | FD(dst_freg), MOVABLE_INS);40334034#else /* SLJIT_MIPS_REV < 1 || SLJIT_MIPS_REV >= 6 */4035SLJIT_SKIP_CHECKS(compiler);4036jump = sljit_emit_jump(compiler, type ^ 0x1);4037FAIL_IF(!jump);40384039if (src1 & SLJIT_MEM)4040FAIL_IF(emit_op_mem(compiler, FLOAT_DATA(type) | LOAD_DATA, FR(dst_freg), src1, src1w));4041else4042FAIL_IF(push_inst(compiler, MOV_fmt(FMT(type)) | FS(src1) | FD(dst_freg), MOVABLE_INS));40434044SLJIT_SKIP_CHECKS(compiler);4045label = sljit_emit_label(compiler);4046FAIL_IF(!label);40474048sljit_set_label(jump, label);4049return SLJIT_SUCCESS;4050#endif /* SLJIT_MIPS_REV >= 1 */4051}40524053#undef FLOAT_DATA4054#undef FMT40554056static sljit_s32 update_mem_addr(struct sljit_compiler *compiler, sljit_s32 *mem, sljit_sw *memw, sljit_s16 max_offset)4057{4058sljit_s32 arg = *mem;4059sljit_sw argw = *memw;40604061if (SLJIT_UNLIKELY(arg & OFFS_REG_MASK)) {4062argw &= 0x3;40634064if (SLJIT_UNLIKELY(argw)) {4065FAIL_IF(push_inst(compiler, SLL_W | T(OFFS_REG(arg)) | D(TMP_REG1) | SH_IMM(argw), DR(TMP_REG1)));4066FAIL_IF(push_inst(compiler, ADDU_W | S(TMP_REG1) | T(arg & REG_MASK) | D(TMP_REG1), DR(TMP_REG1)));4067} else4068FAIL_IF(push_inst(compiler, ADDU_W | S(arg & REG_MASK) | T(OFFS_REG(arg)) | D(TMP_REG1), DR(TMP_REG1)));40694070*mem = TMP_REG1;4071*memw = 0;40724073return SLJIT_SUCCESS;4074}40754076if (argw <= max_offset && argw >= SIMM_MIN) {4077*mem = arg & REG_MASK;4078return SLJIT_SUCCESS;4079}40804081*mem = TMP_REG1;40824083if ((sljit_s16)argw > max_offset) {4084FAIL_IF(load_immediate(compiler, DR(TMP_REG1), argw));4085*memw = 0;4086} else {4087FAIL_IF(load_immediate(compiler, DR(TMP_REG1), TO_ARGW_HI(argw)));4088*memw = (sljit_s16)argw;4089}40904091if ((arg & REG_MASK) == 0)4092return SLJIT_SUCCESS;40934094return push_inst(compiler, ADDU_W | S(TMP_REG1) | T(arg & REG_MASK) | D(TMP_REG1), DR(TMP_REG1));4095}40964097#if (defined SLJIT_LITTLE_ENDIAN && SLJIT_LITTLE_ENDIAN)4098#define IMM_LEFT(memw) IMM((memw) + SSIZE_OF(sw) - 1)4099#define IMM_RIGHT(memw) IMM(memw)4100#define IMM_32_LEFT(memw) IMM((memw) + SSIZE_OF(s32) - 1)4101#define IMM_32_RIGHT(memw) IMM(memw)4102#define IMM_F64_FIRST_LEFT(memw) IMM((memw) + SSIZE_OF(s32) - 1)4103#define IMM_F64_FIRST_RIGHT(memw) IMM(memw)4104#define IMM_F64_SECOND_LEFT(memw) IMM((memw) + SSIZE_OF(f64) - 1)4105#define IMM_F64_SECOND_RIGHT(memw) IMM((memw) + SSIZE_OF(s32))4106#define IMM_16_FIRST(memw) IMM((memw) + 1)4107#define IMM_16_SECOND(memw) IMM(memw)4108#else /* !SLJIT_LITTLE_ENDIAN */4109#define IMM_LEFT(memw) IMM(memw)4110#define IMM_RIGHT(memw) IMM((memw) + SSIZE_OF(sw) - 1)4111#define IMM_32_LEFT(memw) IMM(memw)4112#define IMM_32_RIGHT(memw) IMM((memw) + SSIZE_OF(s32) - 1)4113#define IMM_F64_FIRST_LEFT(memw) IMM((memw) + SSIZE_OF(s32))4114#define IMM_F64_FIRST_RIGHT(memw) IMM((memw) + SSIZE_OF(f64) - 1)4115#define IMM_F64_SECOND_LEFT(memw) IMM(memw)4116#define IMM_F64_SECOND_RIGHT(memw) IMM((memw) + SSIZE_OF(s32) - 1)4117#define IMM_16_FIRST(memw) IMM(memw)4118#define IMM_16_SECOND(memw) IMM((memw) + 1)4119#endif /* SLJIT_LITTLE_ENDIAN */41204121#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)4122#define MEM_CHECK_UNALIGNED(type) ((type) & (SLJIT_MEM_UNALIGNED | SLJIT_MEM_ALIGNED_16))4123#else /* !SLJIT_CONFIG_MIPS_32 */4124#define MEM_CHECK_UNALIGNED(type) ((type) & (SLJIT_MEM_UNALIGNED | SLJIT_MEM_ALIGNED_16 | SLJIT_MEM_ALIGNED_32))4125#endif /* SLJIT_CONFIG_MIPS_32 */41264127SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_mem(struct sljit_compiler *compiler, sljit_s32 type,4128sljit_s32 reg,4129sljit_s32 mem, sljit_sw memw)4130{4131sljit_s32 op = type & 0xff;4132sljit_s32 flags = 0;4133sljit_ins ins;4134#if !(defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 6)4135sljit_ins ins_right;4136#endif /* !(SLJIT_MIPS_REV >= 6) */41374138CHECK_ERROR();4139CHECK(check_sljit_emit_mem(compiler, type, reg, mem, memw));41404141if (reg & REG_PAIR_MASK) {4142ADJUST_LOCAL_OFFSET(mem, memw);41434144#if !(defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 6)4145if (MEM_CHECK_UNALIGNED(type)) {4146FAIL_IF(update_mem_addr(compiler, &mem, &memw, SIMM_MAX - (2 * SSIZE_OF(sw) - 1)));41474148if (!(type & SLJIT_MEM_STORE) && (mem == REG_PAIR_FIRST(reg) || mem == REG_PAIR_SECOND(reg))) {4149FAIL_IF(push_inst(compiler, ADDU_W | S(mem) | TA(0) | D(TMP_REG1), DR(TMP_REG1)));4150mem = TMP_REG1;4151}41524153#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)4154ins = ((type & SLJIT_MEM_STORE) ? SWL : LWL) | S(mem);4155ins_right = ((type & SLJIT_MEM_STORE) ? SWR : LWR) | S(mem);4156#else /* !SLJIT_CONFIG_MIPS_32 */4157ins = ((type & SLJIT_MEM_STORE) ? SDL : LDL) | S(mem);4158ins_right = ((type & SLJIT_MEM_STORE) ? SDR : LDR) | S(mem);4159#endif /* SLJIT_CONFIG_MIPS_32 */41604161FAIL_IF(push_inst(compiler, ins | T(REG_PAIR_FIRST(reg)) | IMM_LEFT(memw), DR(REG_PAIR_FIRST(reg))));4162FAIL_IF(push_inst(compiler, ins_right | T(REG_PAIR_FIRST(reg)) | IMM_RIGHT(memw), DR(REG_PAIR_FIRST(reg))));4163FAIL_IF(push_inst(compiler, ins | T(REG_PAIR_SECOND(reg)) | IMM_LEFT(memw + SSIZE_OF(sw)), DR(REG_PAIR_SECOND(reg))));4164return push_inst(compiler, ins_right | T(REG_PAIR_SECOND(reg)) | IMM_RIGHT(memw + SSIZE_OF(sw)), DR(REG_PAIR_SECOND(reg)));4165}4166#endif /* !(SLJIT_MIPS_REV >= 6) */41674168FAIL_IF(update_mem_addr(compiler, &mem, &memw, SIMM_MAX - SSIZE_OF(sw)));41694170ins = ((type & SLJIT_MEM_STORE) ? STORE_W : LOAD_W) | S(mem);41714172if (!(type & SLJIT_MEM_STORE) && mem == REG_PAIR_FIRST(reg)) {4173FAIL_IF(push_inst(compiler, ins | T(REG_PAIR_SECOND(reg)) | IMM(memw + SSIZE_OF(sw)), DR(REG_PAIR_SECOND(reg))));4174return push_inst(compiler, ins | T(REG_PAIR_FIRST(reg)) | IMM(memw), DR(REG_PAIR_FIRST(reg)));4175}41764177FAIL_IF(push_inst(compiler, ins | T(REG_PAIR_FIRST(reg)) | IMM(memw), DR(REG_PAIR_FIRST(reg))));4178return push_inst(compiler, ins | T(REG_PAIR_SECOND(reg)) | IMM(memw + SSIZE_OF(sw)), DR(REG_PAIR_SECOND(reg)));4179}41804181#if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 6)4182return sljit_emit_mem_unaligned(compiler, type, reg, mem, memw);4183#else /* !(SLJIT_MIPS_REV >= 6) */4184ADJUST_LOCAL_OFFSET(mem, memw);41854186switch (op) {4187case SLJIT_MOV_U8:4188case SLJIT_MOV_S8:4189flags = BYTE_DATA;4190if (!(type & SLJIT_MEM_STORE))4191flags |= LOAD_DATA;41924193if (op == SLJIT_MOV_S8)4194flags |= SIGNED_DATA;41954196return emit_op_mem(compiler, flags, DR(reg), mem, memw);41974198case SLJIT_MOV_U16:4199case SLJIT_MOV_S16:4200FAIL_IF(update_mem_addr(compiler, &mem, &memw, SIMM_MAX - 1));4201SLJIT_ASSERT(FAST_IS_REG(mem) && mem != TMP_REG2);42024203if (type & SLJIT_MEM_STORE) {4204FAIL_IF(push_inst(compiler, SRA_W | T(reg) | D(TMP_REG2) | SH_IMM(8), DR(TMP_REG2)));4205FAIL_IF(push_inst(compiler, data_transfer_insts[BYTE_DATA] | S(mem) | T(TMP_REG2) | IMM_16_FIRST(memw), MOVABLE_INS));4206return push_inst(compiler, data_transfer_insts[BYTE_DATA] | S(mem) | T(reg) | IMM_16_SECOND(memw), MOVABLE_INS);4207}42084209flags = BYTE_DATA | LOAD_DATA;42104211if (op == SLJIT_MOV_S16)4212flags |= SIGNED_DATA;42134214FAIL_IF(push_inst(compiler, data_transfer_insts[flags] | S(mem) | T(TMP_REG2) | IMM_16_FIRST(memw), DR(TMP_REG2)));4215FAIL_IF(push_inst(compiler, data_transfer_insts[BYTE_DATA | LOAD_DATA] | S(mem) | T(reg) | IMM_16_SECOND(memw), DR(reg)));4216FAIL_IF(push_inst(compiler, SLL_W | T(TMP_REG2) | D(TMP_REG2) | SH_IMM(8), DR(TMP_REG2)));4217return push_inst(compiler, OR | S(reg) | T(TMP_REG2) | D(reg), DR(reg));42184219case SLJIT_MOV:4220case SLJIT_MOV_P:4221#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)4222if (type & SLJIT_MEM_ALIGNED_32) {4223flags = WORD_DATA;4224if (!(type & SLJIT_MEM_STORE))4225flags |= LOAD_DATA;42264227return emit_op_mem(compiler, flags, DR(reg), mem, memw);4228}4229#else /* !SLJIT_CONFIG_MIPS_32 */4230FAIL_IF(update_mem_addr(compiler, &mem, &memw, SIMM_MAX - 7));4231SLJIT_ASSERT(FAST_IS_REG(mem) && mem != TMP_REG2);42324233if (type & SLJIT_MEM_STORE) {4234FAIL_IF(push_inst(compiler, SDL | S(mem) | T(reg) | IMM_LEFT(memw), MOVABLE_INS));4235return push_inst(compiler, SDR | S(mem) | T(reg) | IMM_RIGHT(memw), MOVABLE_INS);4236}42374238if (mem == reg) {4239FAIL_IF(push_inst(compiler, ADDU_W | S(mem) | TA(0) | D(TMP_REG1), DR(TMP_REG1)));4240mem = TMP_REG1;4241}42424243FAIL_IF(push_inst(compiler, LDL | S(mem) | T(reg) | IMM_LEFT(memw), DR(reg)));4244return push_inst(compiler, LDR | S(mem) | T(reg) | IMM_RIGHT(memw), DR(reg));4245#endif /* SLJIT_CONFIG_MIPS_32 */4246}42474248FAIL_IF(update_mem_addr(compiler, &mem, &memw, SIMM_MAX - 3));4249SLJIT_ASSERT(FAST_IS_REG(mem) && mem != TMP_REG2);42504251if (type & SLJIT_MEM_STORE) {4252FAIL_IF(push_inst(compiler, SWL | S(mem) | T(reg) | IMM_32_LEFT(memw), MOVABLE_INS));4253return push_inst(compiler, SWR | S(mem) | T(reg) | IMM_32_RIGHT(memw), MOVABLE_INS);4254}42554256if (mem == reg) {4257FAIL_IF(push_inst(compiler, ADDU_W | S(mem) | TA(0) | D(TMP_REG1), DR(TMP_REG1)));4258mem = TMP_REG1;4259}42604261FAIL_IF(push_inst(compiler, LWL | S(mem) | T(reg) | IMM_32_LEFT(memw), DR(reg)));4262#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)4263return push_inst(compiler, LWR | S(mem) | T(reg) | IMM_32_RIGHT(memw), DR(reg));4264#else /* !SLJIT_CONFIG_MIPS_32 */4265FAIL_IF(push_inst(compiler, LWR | S(mem) | T(reg) | IMM_32_RIGHT(memw), DR(reg)));42664267if (op != SLJIT_MOV_U32)4268return SLJIT_SUCCESS;42694270#if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 2)4271return push_inst(compiler, DINSU | T(reg) | SA(0) | (31 << 11), DR(reg));4272#else /* SLJIT_MIPS_REV < 2 */4273FAIL_IF(push_inst(compiler, DSLL32 | T(reg) | D(reg) | SH_IMM(0), DR(reg)));4274return push_inst(compiler, DSRL32 | T(reg) | D(reg) | SH_IMM(0), DR(reg));4275#endif /* SLJIT_MIPS_REV >= 2 */4276#endif /* SLJIT_CONFIG_MIPS_32 */4277#endif /* SLJIT_MIPS_REV >= 6 */4278}42794280#if !(defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 6)42814282SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fmem(struct sljit_compiler *compiler, sljit_s32 type,4283sljit_s32 freg,4284sljit_s32 mem, sljit_sw memw)4285{4286CHECK_ERROR();4287CHECK(check_sljit_emit_fmem(compiler, type, freg, mem, memw));42884289FAIL_IF(update_mem_addr(compiler, &mem, &memw, SIMM_MAX - (type & SLJIT_32) ? 3 : 7));4290SLJIT_ASSERT(FAST_IS_REG(mem) && mem != TMP_REG2);42914292if (type & SLJIT_MEM_STORE) {4293if (type & SLJIT_32) {4294FAIL_IF(push_inst(compiler, MFC1 | T(TMP_REG2) | FS(freg), DR(TMP_REG2)));4295#if !defined(SLJIT_MIPS_REV) || (SLJIT_CONFIG_MIPS_32 && SLJIT_MIPS_REV <= 1)4296FAIL_IF(push_inst(compiler, NOP, UNMOVABLE_INS));4297#endif /* MIPS III */4298FAIL_IF(push_inst(compiler, SWL | S(mem) | T(TMP_REG2) | IMM_32_LEFT(memw), MOVABLE_INS));4299return push_inst(compiler, SWR | S(mem) | T(TMP_REG2) | IMM_32_RIGHT(memw), MOVABLE_INS);4300}43014302#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)4303FAIL_IF(push_inst(compiler, MFC1 | T(TMP_REG2) | FS(freg), DR(TMP_REG2)));4304#if !defined(SLJIT_MIPS_REV) || SLJIT_MIPS_REV <= 14305FAIL_IF(push_inst(compiler, NOP, UNMOVABLE_INS));4306#endif /* MIPS III */4307FAIL_IF(push_inst(compiler, SWL | S(mem) | T(TMP_REG2) | IMM_F64_FIRST_LEFT(memw), MOVABLE_INS));4308FAIL_IF(push_inst(compiler, SWR | S(mem) | T(TMP_REG2) | IMM_F64_FIRST_RIGHT(memw), MOVABLE_INS));4309switch (cpu_feature_list & CPU_FEATURE_FR) {4310#if defined(SLJIT_MIPS_REV) && SLJIT_MIPS_REV >= 24311case CPU_FEATURE_FR:4312FAIL_IF(push_inst(compiler, MFHC1 | T(TMP_REG2) | FS(freg), DR(TMP_REG2)));4313break;4314#endif /* SLJIT_MIPS_REV >= 2 */4315default:4316FAIL_IF(push_inst(compiler, MFC1 | T(TMP_REG2) | FS(freg) | (1 << 11), DR(TMP_REG2)));4317#if !defined(SLJIT_MIPS_REV) || SLJIT_MIPS_REV <= 14318FAIL_IF(push_inst(compiler, NOP, UNMOVABLE_INS));4319#endif4320break;4321}43224323FAIL_IF(push_inst(compiler, SWL | S(mem) | T(TMP_REG2) | IMM_F64_SECOND_LEFT(memw), MOVABLE_INS));4324return push_inst(compiler, SWR | S(mem) | T(TMP_REG2) | IMM_F64_SECOND_RIGHT(memw), MOVABLE_INS);4325#else /* !SLJIT_CONFIG_MIPS_32 */4326FAIL_IF(push_inst(compiler, DMFC1 | T(TMP_REG2) | FS(freg), DR(TMP_REG2)));4327#if !defined(SLJIT_MIPS_REV) || SLJIT_MIPS_REV <= 14328FAIL_IF(push_inst(compiler, NOP, UNMOVABLE_INS));4329#endif /* MIPS III */4330FAIL_IF(push_inst(compiler, SDL | S(mem) | T(TMP_REG2) | IMM_LEFT(memw), MOVABLE_INS));4331return push_inst(compiler, SDR | S(mem) | T(TMP_REG2) | IMM_RIGHT(memw), MOVABLE_INS);4332#endif /* SLJIT_CONFIG_MIPS_32 */4333}43344335if (type & SLJIT_32) {4336FAIL_IF(push_inst(compiler, LWL | S(mem) | T(TMP_REG2) | IMM_32_LEFT(memw), DR(TMP_REG2)));4337FAIL_IF(push_inst(compiler, LWR | S(mem) | T(TMP_REG2) | IMM_32_RIGHT(memw), DR(TMP_REG2)));43384339FAIL_IF(push_inst(compiler, MTC1 | T(TMP_REG2) | FS(freg), MOVABLE_INS));4340#if !defined(SLJIT_MIPS_REV) || (SLJIT_CONFIG_MIPS_32 && SLJIT_MIPS_REV <= 1)4341FAIL_IF(push_inst(compiler, NOP, UNMOVABLE_INS));4342#endif /* MIPS III */4343return SLJIT_SUCCESS;4344}43454346#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)4347FAIL_IF(push_inst(compiler, LWL | S(mem) | T(TMP_REG2) | IMM_F64_FIRST_LEFT(memw), DR(TMP_REG2)));4348FAIL_IF(push_inst(compiler, LWR | S(mem) | T(TMP_REG2) | IMM_F64_FIRST_RIGHT(memw), DR(TMP_REG2)));4349FAIL_IF(push_inst(compiler, MTC1 | T(TMP_REG2) | FS(freg), MOVABLE_INS));43504351FAIL_IF(push_inst(compiler, LWL | S(mem) | T(TMP_REG2) | IMM_F64_SECOND_LEFT(memw), DR(TMP_REG2)));4352FAIL_IF(push_inst(compiler, LWR | S(mem) | T(TMP_REG2) | IMM_F64_SECOND_RIGHT(memw), DR(TMP_REG2)));4353switch (cpu_feature_list & CPU_FEATURE_FR) {4354#if defined(SLJIT_MIPS_REV) && SLJIT_MIPS_REV >= 24355case CPU_FEATURE_FR:4356return push_inst(compiler, MTHC1 | T(TMP_REG2) | FS(freg), MOVABLE_INS);4357#endif /* SLJIT_MIPS_REV >= 2 */4358default:4359FAIL_IF(push_inst(compiler, MTC1 | T(TMP_REG2) | FS(freg) | (1 << 11), MOVABLE_INS));4360break;4361}4362#else /* !SLJIT_CONFIG_MIPS_32 */4363FAIL_IF(push_inst(compiler, LDL | S(mem) | T(TMP_REG2) | IMM_LEFT(memw), DR(TMP_REG2)));4364FAIL_IF(push_inst(compiler, LDR | S(mem) | T(TMP_REG2) | IMM_RIGHT(memw), DR(TMP_REG2)));43654366FAIL_IF(push_inst(compiler, DMTC1 | T(TMP_REG2) | FS(freg), MOVABLE_INS));4367#endif /* SLJIT_CONFIG_MIPS_32 */4368#if !defined(SLJIT_MIPS_REV) || SLJIT_MIPS_REV <= 14369FAIL_IF(push_inst(compiler, NOP, UNMOVABLE_INS));4370#endif /* MIPS III */4371return SLJIT_SUCCESS;4372}43734374#endif /* !SLJIT_MIPS_REV || SLJIT_MIPS_REV < 6 */43754376#undef IMM_16_SECOND4377#undef IMM_16_FIRST4378#undef IMM_F64_SECOND_RIGHT4379#undef IMM_F64_SECOND_LEFT4380#undef IMM_F64_FIRST_RIGHT4381#undef IMM_F64_FIRST_LEFT4382#undef IMM_32_RIGHT4383#undef IMM_32_LEFT4384#undef IMM_RIGHT4385#undef IMM_LEFT4386#undef MEM_CHECK_UNALIGNED43874388#undef TO_ARGW_HI43894390SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_atomic_load(struct sljit_compiler *compiler, sljit_s32 op,4391sljit_s32 dst_reg,4392sljit_s32 mem_reg)4393{4394sljit_ins ins;43954396CHECK_ERROR();4397CHECK(check_sljit_emit_atomic_load(compiler, op, dst_reg, mem_reg));43984399if (op & SLJIT_ATOMIC_USE_CAS)4400return SLJIT_ERR_UNSUPPORTED;44014402switch (GET_OPCODE(op)) {4403case SLJIT_MOV:4404case SLJIT_MOV_P:4405#if (defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64)4406ins = LLD;4407break;4408#endif /* SLJIT_CONFIG_MIPS_64 */4409case SLJIT_MOV_S32:4410case SLJIT_MOV32:4411ins = LL;4412break;44134414default:4415return SLJIT_ERR_UNSUPPORTED;4416}44174418if (op & SLJIT_ATOMIC_TEST)4419return SLJIT_SUCCESS;44204421return push_inst(compiler, ins | T(dst_reg) | S(mem_reg), DR(dst_reg));4422}44234424SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_atomic_store(struct sljit_compiler *compiler, sljit_s32 op,4425sljit_s32 src_reg,4426sljit_s32 mem_reg,4427sljit_s32 temp_reg)4428{4429sljit_ins ins;44304431/* temp_reg == mem_reg is undefined so use another temp register */4432SLJIT_UNUSED_ARG(temp_reg);44334434CHECK_ERROR();4435CHECK(check_sljit_emit_atomic_store(compiler, op, src_reg, mem_reg, temp_reg));44364437if (op & SLJIT_ATOMIC_USE_CAS)4438return SLJIT_ERR_UNSUPPORTED;44394440switch (GET_OPCODE(op)) {4441case SLJIT_MOV:4442case SLJIT_MOV_P:4443#if (defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64)4444ins = SCD;4445break;4446#endif /* SLJIT_CONFIG_MIPS_64 */4447case SLJIT_MOV_S32:4448case SLJIT_MOV32:4449op |= SLJIT_32;4450ins = SC;4451break;44524453default:4454return SLJIT_ERR_UNSUPPORTED;4455}44564457if (op & SLJIT_ATOMIC_TEST)4458return SLJIT_SUCCESS;44594460FAIL_IF(push_inst(compiler, SELECT_OP(DADDU, ADDU) | S(src_reg) | TA(0) | DA(OTHER_FLAG), OTHER_FLAG));4461return push_inst(compiler, ins | TA(OTHER_FLAG) | S(mem_reg), OTHER_FLAG);4462}44634464SLJIT_API_FUNC_ATTRIBUTE struct sljit_const* sljit_emit_const(struct sljit_compiler *compiler, sljit_s32 op,4465sljit_s32 dst, sljit_sw dstw,4466sljit_sw init_value)4467{4468struct sljit_const *const_;4469sljit_s32 dst_r;4470sljit_s32 mem_flags = WORD_DATA;44714472CHECK_ERROR_PTR();4473CHECK_PTR(check_sljit_emit_const(compiler, op, dst, dstw, init_value));4474ADJUST_LOCAL_OFFSET(dst, dstw);44754476const_ = (struct sljit_const*)ensure_abuf(compiler, sizeof(struct sljit_const));4477PTR_FAIL_IF(!const_);4478set_const(const_, compiler);44794480dst_r = FAST_IS_REG(dst) ? dst : TMP_REG2;44814482switch (GET_OPCODE(op)) {4483case SLJIT_MOV_U8:4484if (init_value & 0x100)4485init_value |= 0xff00;4486else4487init_value &= 0xff;44884489PTR_FAIL_IF(push_inst(compiler, ADDIU | SA(0) | T(dst_r) | IMM(init_value), DR(dst_r)));4490mem_flags = BYTE_DATA;4491break;44924493#if (defined(SLJIT_CONFIG_MIPS_64) && SLJIT_CONFIG_MIPS_64)4494case SLJIT_MOV32:4495mem_flags = INT_DATA;4496SLJIT_FALLTHROUGH4497case SLJIT_MOV_S32:4498PTR_FAIL_IF(push_inst(compiler, LUI | T(dst_r) | IMM(init_value >> 16), DR(dst_r)));4499PTR_FAIL_IF(push_inst(compiler, ORI | S(dst_r) | T(dst_r) | IMM(init_value), DR(dst_r)));4500break;4501#endif /* SLJIT_CONFIG_MIPS_64 */45024503default:4504PTR_FAIL_IF(emit_const(compiler, dst_r, init_value));4505break;4506}45074508if (dst & SLJIT_MEM)4509PTR_FAIL_IF(emit_op_mem(compiler, mem_flags, DR(TMP_REG2), dst, dstw));45104511return const_;4512}45134514SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_op_addr(struct sljit_compiler *compiler, sljit_s32 op,4515sljit_s32 dst, sljit_sw dstw)4516{4517struct sljit_jump *jump;4518sljit_s32 dst_r, target_r;4519SLJIT_UNUSED_ARG(op);45204521CHECK_ERROR_PTR();4522CHECK_PTR(check_sljit_emit_op_addr(compiler, op, dst, dstw));4523ADJUST_LOCAL_OFFSET(dst, dstw);45244525dst_r = FAST_IS_REG(dst) ? dst : TMP_REG2;45264527if (op != SLJIT_ADD_ABS_ADDR)4528target_r = dst_r;4529else {4530target_r = TMP_REG1;45314532if (dst & SLJIT_MEM)4533PTR_FAIL_IF(emit_op_mem(compiler, WORD_DATA | LOAD_DATA, DR(TMP_REG2), dst, dstw));4534}45354536jump = (struct sljit_jump*)ensure_abuf(compiler, sizeof(struct sljit_jump));4537PTR_FAIL_IF(!jump);4538set_mov_addr(jump, compiler, 0);45394540PTR_FAIL_IF(push_inst(compiler, (sljit_ins)target_r, UNMOVABLE_INS));4541#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)4542compiler->size += 1;4543#else4544compiler->size += 5;4545#endif45464547if (op == SLJIT_ADD_ABS_ADDR)4548PTR_FAIL_IF(push_inst(compiler, ADDU_W | S(dst_r) | T(TMP_REG1) | D(dst_r), DR(dst_r)));45494550if (dst & SLJIT_MEM)4551PTR_FAIL_IF(emit_op_mem(compiler, WORD_DATA, DR(TMP_REG2), dst, dstw));45524553return jump;4554}45554556SLJIT_API_FUNC_ATTRIBUTE void sljit_set_const(sljit_uw addr, sljit_s32 op, sljit_sw new_constant, sljit_sw executable_offset)4557{4558sljit_ins *inst;45594560switch (GET_OPCODE(op)) {4561case SLJIT_MOV_U8:4562inst = (sljit_ins *)addr;4563SLJIT_ASSERT((inst[0] & 0xfc000000) == ADDIU);45644565if (new_constant & 0x100)4566new_constant |= 0xff00;4567else4568new_constant &= 0xff;45694570SLJIT_UPDATE_WX_FLAGS(inst, inst + 1, 0);4571inst[0] = (inst[0] & 0xffff0000) | IMM(new_constant);4572SLJIT_UPDATE_WX_FLAGS(inst, inst + 1, 1);4573inst = (sljit_ins *)SLJIT_ADD_EXEC_OFFSET(inst, executable_offset);4574SLJIT_CACHE_FLUSH(inst, inst + 1);4575return;45764577#if (defined(SLJIT_CONFIG_MIPS_64) && SLJIT_CONFIG_MIPS_64)4578case SLJIT_MOV32:4579case SLJIT_MOV_S32:4580inst = (sljit_ins *)addr;4581SLJIT_ASSERT((inst[0] & 0xffe00000) == LUI && (inst[1] & 0xfc000000) == ORI);45824583SLJIT_UPDATE_WX_FLAGS(inst, inst + 2, 0);4584inst[0] = (inst[0] & 0xffff0000) | IMM(new_constant >> 16);4585inst[1] = (inst[1] & 0xffff0000) | IMM(new_constant);4586SLJIT_UPDATE_WX_FLAGS(inst, inst + 2, 1);4587inst = (sljit_ins *)SLJIT_ADD_EXEC_OFFSET(inst, executable_offset);4588SLJIT_CACHE_FLUSH(inst, inst + 2);4589return;4590#endif /* SLJIT_CONFIG_MIPS_64 */45914592default:4593sljit_set_jump_addr(addr, (sljit_uw)new_constant, executable_offset);4594return;4595}4596}459745984599