"Fossies" - the Fresh Open Source Software Archive

Member "pcre-8.44/sljit/sljitNativeMIPS_32.c" (17 Jul 2019, 24431 Bytes) of package /linux/misc/pcre-8.44.tar.bz2:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "sljitNativeMIPS_32.c" see the Fossies "Dox" file reference documentation and the latest Fossies "Diffs" side-by-side code changes report: 8.43_vs_8.44.

    1 /*
    2  *    Stack-less Just-In-Time compiler
    3  *
    4  *    Copyright Zoltan Herczeg (hzmester@freemail.hu). All rights reserved.
    5  *
    6  * Redistribution and use in source and binary forms, with or without modification, are
    7  * permitted provided that the following conditions are met:
    8  *
    9  *   1. Redistributions of source code must retain the above copyright notice, this list of
   10  *      conditions and the following disclaimer.
   11  *
   12  *   2. Redistributions in binary form must reproduce the above copyright notice, this list
   13  *      of conditions and the following disclaimer in the documentation and/or other materials
   14  *      provided with the distribution.
   15  *
   16  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) AND CONTRIBUTORS ``AS IS'' AND ANY
   17  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   18  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
   19  * SHALL THE COPYRIGHT HOLDER(S) OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
   20  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
   21  * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
   22  * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
   23  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
   24  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
   25  */
   26 
   27 /* mips 32-bit arch dependent functions. */
   28 
   29 static sljit_s32 load_immediate(struct sljit_compiler *compiler, sljit_s32 dst_ar, sljit_sw imm)
   30 {
   31     if (!(imm & ~0xffff))
   32         return push_inst(compiler, ORI | SA(0) | TA(dst_ar) | IMM(imm), dst_ar);
   33 
   34     if (imm < 0 && imm >= SIMM_MIN)
   35         return push_inst(compiler, ADDIU | SA(0) | TA(dst_ar) | IMM(imm), dst_ar);
   36 
   37     FAIL_IF(push_inst(compiler, LUI | TA(dst_ar) | IMM(imm >> 16), dst_ar));
   38     return (imm & 0xffff) ? push_inst(compiler, ORI | SA(dst_ar) | TA(dst_ar) | IMM(imm), dst_ar) : SLJIT_SUCCESS;
   39 }
   40 
   41 #define EMIT_LOGICAL(op_imm, op_norm) \
   42     if (flags & SRC2_IMM) { \
   43         if (op & SLJIT_SET_Z) \
   44             FAIL_IF(push_inst(compiler, op_imm | S(src1) | TA(EQUAL_FLAG) | IMM(src2), EQUAL_FLAG)); \
   45         if (!(flags & UNUSED_DEST)) \
   46             FAIL_IF(push_inst(compiler, op_imm | S(src1) | T(dst) | IMM(src2), DR(dst))); \
   47     } \
   48     else { \
   49         if (op & SLJIT_SET_Z) \
   50             FAIL_IF(push_inst(compiler, op_norm | S(src1) | T(src2) | DA(EQUAL_FLAG), EQUAL_FLAG)); \
   51         if (!(flags & UNUSED_DEST)) \
   52             FAIL_IF(push_inst(compiler, op_norm | S(src1) | T(src2) | D(dst), DR(dst))); \
   53     }
   54 
   55 #define EMIT_SHIFT(op_imm, op_v) \
   56     if (flags & SRC2_IMM) { \
   57         if (op & SLJIT_SET_Z) \
   58             FAIL_IF(push_inst(compiler, op_imm | T(src1) | DA(EQUAL_FLAG) | SH_IMM(src2), EQUAL_FLAG)); \
   59         if (!(flags & UNUSED_DEST)) \
   60             FAIL_IF(push_inst(compiler, op_imm | T(src1) | D(dst) | SH_IMM(src2), DR(dst))); \
   61     } \
   62     else { \
   63         if (op & SLJIT_SET_Z) \
   64             FAIL_IF(push_inst(compiler, op_v | S(src2) | T(src1) | DA(EQUAL_FLAG), EQUAL_FLAG)); \
   65         if (!(flags & UNUSED_DEST)) \
   66             FAIL_IF(push_inst(compiler, op_v | S(src2) | T(src1) | D(dst), DR(dst))); \
   67     }
   68 
   69 static SLJIT_INLINE sljit_s32 emit_single_op(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 flags,
   70     sljit_s32 dst, sljit_s32 src1, sljit_sw src2)
   71 {
   72     sljit_s32 is_overflow, is_carry, is_handled;
   73 
   74     switch (GET_OPCODE(op)) {
   75     case SLJIT_MOV:
   76     case SLJIT_MOV_U32:
   77     case SLJIT_MOV_S32:
   78     case SLJIT_MOV_P:
   79         SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & SRC2_IMM));
   80         if (dst != src2)
   81             return push_inst(compiler, ADDU | S(src2) | TA(0) | D(dst), DR(dst));
   82         return SLJIT_SUCCESS;
   83 
   84     case SLJIT_MOV_U8:
   85     case SLJIT_MOV_S8:
   86         SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & SRC2_IMM));
   87         if ((flags & (REG_DEST | REG2_SOURCE)) == (REG_DEST | REG2_SOURCE)) {
   88             if (op == SLJIT_MOV_S8) {
   89 #if (defined SLJIT_MIPS_R1 && SLJIT_MIPS_R1)
   90                 return push_inst(compiler, SEB | T(src2) | D(dst), DR(dst));
   91 #else
   92                 FAIL_IF(push_inst(compiler, SLL | T(src2) | D(dst) | SH_IMM(24), DR(dst)));
   93                 return push_inst(compiler, SRA | T(dst) | D(dst) | SH_IMM(24), DR(dst));
   94 #endif
   95             }
   96             return push_inst(compiler, ANDI | S(src2) | T(dst) | IMM(0xff), DR(dst));
   97         }
   98         else {
   99             SLJIT_ASSERT(dst == src2);
  100         }
  101         return SLJIT_SUCCESS;
  102 
  103     case SLJIT_MOV_U16:
  104     case SLJIT_MOV_S16:
  105         SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & SRC2_IMM));
  106         if ((flags & (REG_DEST | REG2_SOURCE)) == (REG_DEST | REG2_SOURCE)) {
  107             if (op == SLJIT_MOV_S16) {
  108 #if (defined SLJIT_MIPS_R1 && SLJIT_MIPS_R1)
  109                 return push_inst(compiler, SEH | T(src2) | D(dst), DR(dst));
  110 #else
  111                 FAIL_IF(push_inst(compiler, SLL | T(src2) | D(dst) | SH_IMM(16), DR(dst)));
  112                 return push_inst(compiler, SRA | T(dst) | D(dst) | SH_IMM(16), DR(dst));
  113 #endif
  114             }
  115             return push_inst(compiler, ANDI | S(src2) | T(dst) | IMM(0xffff), DR(dst));
  116         }
  117         else {
  118             SLJIT_ASSERT(dst == src2);
  119         }
  120         return SLJIT_SUCCESS;
  121 
  122     case SLJIT_NOT:
  123         SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & SRC2_IMM));
  124         if (op & SLJIT_SET_Z)
  125             FAIL_IF(push_inst(compiler, NOR | S(src2) | T(src2) | DA(EQUAL_FLAG), EQUAL_FLAG));
  126         if (!(flags & UNUSED_DEST))
  127             FAIL_IF(push_inst(compiler, NOR | S(src2) | T(src2) | D(dst), DR(dst)));
  128         return SLJIT_SUCCESS;
  129 
  130     case SLJIT_CLZ:
  131         SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & SRC2_IMM));
  132 #if (defined SLJIT_MIPS_R1 && SLJIT_MIPS_R1)
  133         if (op & SLJIT_SET_Z)
  134             FAIL_IF(push_inst(compiler, CLZ | S(src2) | TA(EQUAL_FLAG) | DA(EQUAL_FLAG), EQUAL_FLAG));
  135         if (!(flags & UNUSED_DEST))
  136             FAIL_IF(push_inst(compiler, CLZ | S(src2) | T(dst) | D(dst), DR(dst)));
  137 #else
  138         if (SLJIT_UNLIKELY(flags & UNUSED_DEST)) {
  139             FAIL_IF(push_inst(compiler, SRL | T(src2) | DA(EQUAL_FLAG) | SH_IMM(31), EQUAL_FLAG));
  140             return push_inst(compiler, XORI | SA(EQUAL_FLAG) | TA(EQUAL_FLAG) | IMM(1), EQUAL_FLAG);
  141         }
  142         /* Nearly all instructions are unmovable in the following sequence. */
  143         FAIL_IF(push_inst(compiler, ADDU | S(src2) | TA(0) | D(TMP_REG1), DR(TMP_REG1)));
  144         /* Check zero. */
  145         FAIL_IF(push_inst(compiler, BEQ | S(TMP_REG1) | TA(0) | IMM(5), UNMOVABLE_INS));
  146         FAIL_IF(push_inst(compiler, ORI | SA(0) | T(dst) | IMM(32), UNMOVABLE_INS));
  147         FAIL_IF(push_inst(compiler, ADDIU | SA(0) | T(dst) | IMM(-1), DR(dst)));
  148         /* Loop for searching the highest bit. */
  149         FAIL_IF(push_inst(compiler, ADDIU | S(dst) | T(dst) | IMM(1), DR(dst)));
  150         FAIL_IF(push_inst(compiler, BGEZ | S(TMP_REG1) | IMM(-2), UNMOVABLE_INS));
  151         FAIL_IF(push_inst(compiler, SLL | T(TMP_REG1) | D(TMP_REG1) | SH_IMM(1), UNMOVABLE_INS));
  152 #endif
  153         return SLJIT_SUCCESS;
  154 
  155     case SLJIT_ADD:
  156         is_overflow = GET_FLAG_TYPE(op) == SLJIT_OVERFLOW;
  157         is_carry = GET_FLAG_TYPE(op) == GET_FLAG_TYPE(SLJIT_SET_CARRY);
  158 
  159         if (flags & SRC2_IMM) {
  160             if (is_overflow) {
  161                 if (src2 >= 0)
  162                     FAIL_IF(push_inst(compiler, OR | S(src1) | T(src1) | DA(EQUAL_FLAG), EQUAL_FLAG));
  163                 else
  164                     FAIL_IF(push_inst(compiler, NOR | S(src1) | T(src1) | DA(EQUAL_FLAG), EQUAL_FLAG));
  165             }
  166             else if (op & SLJIT_SET_Z)
  167                 FAIL_IF(push_inst(compiler, ADDIU | S(src1) | TA(EQUAL_FLAG) | IMM(src2), EQUAL_FLAG));
  168 
  169             if (is_overflow || is_carry) {
  170                 if (src2 >= 0)
  171                     FAIL_IF(push_inst(compiler, ORI | S(src1) | TA(OTHER_FLAG) | IMM(src2), OTHER_FLAG));
  172                 else {
  173                     FAIL_IF(push_inst(compiler, ADDIU | SA(0) | TA(OTHER_FLAG) | IMM(src2), OTHER_FLAG));
  174                     FAIL_IF(push_inst(compiler, OR | S(src1) | TA(OTHER_FLAG) | DA(OTHER_FLAG), OTHER_FLAG));
  175                 }
  176             }
  177             /* dst may be the same as src1 or src2. */
  178             if (!(flags & UNUSED_DEST) || (op & VARIABLE_FLAG_MASK))
  179                 FAIL_IF(push_inst(compiler, ADDIU | S(src1) | T(dst) | IMM(src2), DR(dst)));
  180         }
  181         else {
  182             if (is_overflow)
  183                 FAIL_IF(push_inst(compiler, XOR | S(src1) | T(src2) | DA(EQUAL_FLAG), EQUAL_FLAG));
  184             else if (op & SLJIT_SET_Z)
  185                 FAIL_IF(push_inst(compiler, ADDU | S(src1) | T(src2) | DA(EQUAL_FLAG), EQUAL_FLAG));
  186 
  187             if (is_overflow || is_carry)
  188                 FAIL_IF(push_inst(compiler, OR | S(src1) | T(src2) | DA(OTHER_FLAG), OTHER_FLAG));
  189             /* dst may be the same as src1 or src2. */
  190             if (!(flags & UNUSED_DEST) || (op & VARIABLE_FLAG_MASK))
  191                 FAIL_IF(push_inst(compiler, ADDU | S(src1) | T(src2) | D(dst), DR(dst)));
  192         }
  193 
  194         /* a + b >= a | b (otherwise, the carry should be set to 1). */
  195         if (is_overflow || is_carry)
  196             FAIL_IF(push_inst(compiler, SLTU | S(dst) | TA(OTHER_FLAG) | DA(OTHER_FLAG), OTHER_FLAG));
  197         if (!is_overflow)
  198             return SLJIT_SUCCESS;
  199         FAIL_IF(push_inst(compiler, SLL | TA(OTHER_FLAG) | D(TMP_REG1) | SH_IMM(31), DR(TMP_REG1)));
  200         FAIL_IF(push_inst(compiler, XOR | S(TMP_REG1) | TA(EQUAL_FLAG) | DA(EQUAL_FLAG), EQUAL_FLAG));
  201         FAIL_IF(push_inst(compiler, XOR | S(dst) | TA(EQUAL_FLAG) | DA(OTHER_FLAG), OTHER_FLAG));
  202         if (op & SLJIT_SET_Z)
  203             FAIL_IF(push_inst(compiler, ADDU | S(dst) | TA(0) | DA(EQUAL_FLAG), EQUAL_FLAG));
  204         return push_inst(compiler, SRL | TA(OTHER_FLAG) | DA(OTHER_FLAG) | SH_IMM(31), OTHER_FLAG);
  205 
  206     case SLJIT_ADDC:
  207         is_carry = GET_FLAG_TYPE(op) == GET_FLAG_TYPE(SLJIT_SET_CARRY);
  208 
  209         if (flags & SRC2_IMM) {
  210             if (is_carry) {
  211                 if (src2 >= 0)
  212                     FAIL_IF(push_inst(compiler, ORI | S(src1) | TA(EQUAL_FLAG) | IMM(src2), EQUAL_FLAG));
  213                 else {
  214                     FAIL_IF(push_inst(compiler, ADDIU | SA(0) | TA(EQUAL_FLAG) | IMM(src2), EQUAL_FLAG));
  215                     FAIL_IF(push_inst(compiler, OR | S(src1) | TA(EQUAL_FLAG) | DA(EQUAL_FLAG), EQUAL_FLAG));
  216                 }
  217             }
  218             FAIL_IF(push_inst(compiler, ADDIU | S(src1) | T(dst) | IMM(src2), DR(dst)));
  219         } else {
  220             if (is_carry)
  221                 FAIL_IF(push_inst(compiler, OR | S(src1) | T(src2) | DA(EQUAL_FLAG), EQUAL_FLAG));
  222             /* dst may be the same as src1 or src2. */
  223             FAIL_IF(push_inst(compiler, ADDU | S(src1) | T(src2) | D(dst), DR(dst)));
  224         }
  225         if (is_carry)
  226             FAIL_IF(push_inst(compiler, SLTU | S(dst) | TA(EQUAL_FLAG) | DA(EQUAL_FLAG), EQUAL_FLAG));
  227 
  228         FAIL_IF(push_inst(compiler, ADDU | S(dst) | TA(OTHER_FLAG) | D(dst), DR(dst)));
  229         if (!is_carry)
  230             return SLJIT_SUCCESS;
  231 
  232         /* Set ULESS_FLAG (dst == 0) && (OTHER_FLAG == 1). */
  233         FAIL_IF(push_inst(compiler, SLTU | S(dst) | TA(OTHER_FLAG) | DA(OTHER_FLAG), OTHER_FLAG));
  234         /* Set carry flag. */
  235         return push_inst(compiler, OR | SA(OTHER_FLAG) | TA(EQUAL_FLAG) | DA(OTHER_FLAG), OTHER_FLAG);
  236 
  237     case SLJIT_SUB:
  238         if ((flags & SRC2_IMM) && src2 == SIMM_MIN) {
  239             FAIL_IF(push_inst(compiler, ADDIU | SA(0) | T(TMP_REG2) | IMM(src2), DR(TMP_REG2)));
  240             src2 = TMP_REG2;
  241             flags &= ~SRC2_IMM;
  242         }
  243 
  244         is_handled = 0;
  245 
  246         if (flags & SRC2_IMM) {
  247             if (GET_FLAG_TYPE(op) == SLJIT_LESS || GET_FLAG_TYPE(op) == SLJIT_GREATER_EQUAL) {
  248                 FAIL_IF(push_inst(compiler, SLTIU | S(src1) | TA(OTHER_FLAG) | IMM(src2), OTHER_FLAG));
  249                 is_handled = 1;
  250             }
  251             else if (GET_FLAG_TYPE(op) == SLJIT_SIG_LESS || GET_FLAG_TYPE(op) == SLJIT_SIG_GREATER_EQUAL) {
  252                 FAIL_IF(push_inst(compiler, SLTI | S(src1) | TA(OTHER_FLAG) | IMM(src2), OTHER_FLAG));
  253                 is_handled = 1;
  254             }
  255         }
  256 
  257         if (!is_handled && GET_FLAG_TYPE(op) >= SLJIT_LESS && GET_FLAG_TYPE(op) <= SLJIT_SIG_LESS_EQUAL) {
  258             is_handled = 1;
  259 
  260             if (flags & SRC2_IMM) {
  261                 FAIL_IF(push_inst(compiler, ADDIU | SA(0) | T(TMP_REG2) | IMM(src2), DR(TMP_REG2)));
  262                 src2 = TMP_REG2;
  263                 flags &= ~SRC2_IMM;
  264             }
  265 
  266             if (GET_FLAG_TYPE(op) == SLJIT_LESS || GET_FLAG_TYPE(op) == SLJIT_GREATER_EQUAL) {
  267                 FAIL_IF(push_inst(compiler, SLTU | S(src1) | T(src2) | DA(OTHER_FLAG), OTHER_FLAG));
  268             }
  269             else if (GET_FLAG_TYPE(op) == SLJIT_GREATER || GET_FLAG_TYPE(op) == SLJIT_LESS_EQUAL)
  270             {
  271                 FAIL_IF(push_inst(compiler, SLTU | S(src2) | T(src1) | DA(OTHER_FLAG), OTHER_FLAG));
  272             }
  273             else if (GET_FLAG_TYPE(op) == SLJIT_SIG_LESS || GET_FLAG_TYPE(op) == SLJIT_SIG_GREATER_EQUAL) {
  274                 FAIL_IF(push_inst(compiler, SLT | S(src1) | T(src2) | DA(OTHER_FLAG), OTHER_FLAG));
  275             }
  276             else if (GET_FLAG_TYPE(op) == SLJIT_SIG_GREATER || GET_FLAG_TYPE(op) == SLJIT_SIG_LESS_EQUAL)
  277             {
  278                 FAIL_IF(push_inst(compiler, SLT | S(src2) | T(src1) | DA(OTHER_FLAG), OTHER_FLAG));
  279             }
  280         }
  281 
  282         if (is_handled) {
  283             if (flags & SRC2_IMM) {
  284                 if (op & SLJIT_SET_Z)
  285                     FAIL_IF(push_inst(compiler, ADDIU | S(src1) | TA(EQUAL_FLAG) | IMM(-src2), EQUAL_FLAG));
  286                 if (!(flags & UNUSED_DEST))
  287                     return push_inst(compiler, ADDIU | S(src1) | T(dst) | IMM(-src2), DR(dst));
  288             }
  289             else {
  290                 if (op & SLJIT_SET_Z)
  291                     FAIL_IF(push_inst(compiler, SUBU | S(src1) | T(src2) | DA(EQUAL_FLAG), EQUAL_FLAG));
  292                 if (!(flags & UNUSED_DEST))
  293                     return push_inst(compiler, SUBU | S(src1) | T(src2) | D(dst), DR(dst));
  294             }
  295             return SLJIT_SUCCESS;
  296         }
  297 
  298         is_overflow = GET_FLAG_TYPE(op) == SLJIT_OVERFLOW;
  299         is_carry = GET_FLAG_TYPE(op) == GET_FLAG_TYPE(SLJIT_SET_CARRY);
  300 
  301         if (flags & SRC2_IMM) {
  302             if (is_overflow) {
  303                 if (src2 >= 0)
  304                     FAIL_IF(push_inst(compiler, OR | S(src1) | T(src1) | DA(EQUAL_FLAG), EQUAL_FLAG));
  305                 else
  306                     FAIL_IF(push_inst(compiler, NOR | S(src1) | T(src1) | DA(EQUAL_FLAG), EQUAL_FLAG));
  307             }
  308             else if (op & SLJIT_SET_Z)
  309                 FAIL_IF(push_inst(compiler, ADDIU | S(src1) | TA(EQUAL_FLAG) | IMM(-src2), EQUAL_FLAG));
  310 
  311             if (is_overflow || is_carry)
  312                 FAIL_IF(push_inst(compiler, SLTIU | S(src1) | TA(OTHER_FLAG) | IMM(src2), OTHER_FLAG));
  313             /* dst may be the same as src1 or src2. */
  314             if (!(flags & UNUSED_DEST) || (op & VARIABLE_FLAG_MASK))
  315                 FAIL_IF(push_inst(compiler, ADDIU | S(src1) | T(dst) | IMM(-src2), DR(dst)));
  316         }
  317         else {
  318             if (is_overflow)
  319                 FAIL_IF(push_inst(compiler, XOR | S(src1) | T(src2) | DA(EQUAL_FLAG), EQUAL_FLAG));
  320             else if (op & SLJIT_SET_Z)
  321                 FAIL_IF(push_inst(compiler, SUBU | S(src1) | T(src2) | DA(EQUAL_FLAG), EQUAL_FLAG));
  322 
  323             if (is_overflow || is_carry)
  324                 FAIL_IF(push_inst(compiler, SLTU | S(src1) | T(src2) | DA(OTHER_FLAG), OTHER_FLAG));
  325             /* dst may be the same as src1 or src2. */
  326             if (!(flags & UNUSED_DEST) || (op & VARIABLE_FLAG_MASK))
  327                 FAIL_IF(push_inst(compiler, SUBU | S(src1) | T(src2) | D(dst), DR(dst)));
  328         }
  329 
  330         if (!is_overflow)
  331             return SLJIT_SUCCESS;
  332         FAIL_IF(push_inst(compiler, SLL | TA(OTHER_FLAG) | D(TMP_REG1) | SH_IMM(31), DR(TMP_REG1)));
  333         FAIL_IF(push_inst(compiler, XOR | S(TMP_REG1) | TA(EQUAL_FLAG) | DA(EQUAL_FLAG), EQUAL_FLAG));
  334         FAIL_IF(push_inst(compiler, XOR | S(dst) | TA(EQUAL_FLAG) | DA(OTHER_FLAG), OTHER_FLAG));
  335         if (op & SLJIT_SET_Z)
  336             FAIL_IF(push_inst(compiler, ADDU | S(dst) | TA(0) | DA(EQUAL_FLAG), EQUAL_FLAG));
  337         return push_inst(compiler, SRL | TA(OTHER_FLAG) | DA(OTHER_FLAG) | SH_IMM(31), OTHER_FLAG);
  338 
  339     case SLJIT_SUBC:
  340         if ((flags & SRC2_IMM) && src2 == SIMM_MIN) {
  341             FAIL_IF(push_inst(compiler, ADDIU | SA(0) | T(TMP_REG2) | IMM(src2), DR(TMP_REG2)));
  342             src2 = TMP_REG2;
  343             flags &= ~SRC2_IMM;
  344         }
  345 
  346         is_carry = GET_FLAG_TYPE(op) == GET_FLAG_TYPE(SLJIT_SET_CARRY);
  347 
  348         if (flags & SRC2_IMM) {
  349             if (is_carry)
  350                 FAIL_IF(push_inst(compiler, SLTIU | S(src1) | TA(EQUAL_FLAG) | IMM(src2), EQUAL_FLAG));
  351             /* dst may be the same as src1 or src2. */
  352             FAIL_IF(push_inst(compiler, ADDIU | S(src1) | T(dst) | IMM(-src2), DR(dst)));
  353         }
  354         else {
  355             if (is_carry)
  356                 FAIL_IF(push_inst(compiler, SLTU | S(src1) | T(src2) | DA(EQUAL_FLAG), EQUAL_FLAG));
  357             /* dst may be the same as src1 or src2. */
  358             FAIL_IF(push_inst(compiler, SUBU | S(src1) | T(src2) | D(dst), DR(dst)));
  359         }
  360 
  361         if (is_carry)
  362             FAIL_IF(push_inst(compiler, SLTU | S(dst) | TA(OTHER_FLAG) | D(TMP_REG1), DR(TMP_REG1)));
  363 
  364         FAIL_IF(push_inst(compiler, SUBU | S(dst) | TA(OTHER_FLAG) | D(dst), DR(dst)));
  365         return (is_carry) ? push_inst(compiler, OR | SA(EQUAL_FLAG) | T(TMP_REG1) | DA(OTHER_FLAG), OTHER_FLAG) : SLJIT_SUCCESS;
  366 
  367     case SLJIT_MUL:
  368         SLJIT_ASSERT(!(flags & SRC2_IMM));
  369 
  370         if (GET_FLAG_TYPE(op) != SLJIT_MUL_OVERFLOW) {
  371 #if (defined SLJIT_MIPS_R1 && SLJIT_MIPS_R1) || (defined SLJIT_MIPS_R6 && SLJIT_MIPS_R6)
  372             return push_inst(compiler, MUL | S(src1) | T(src2) | D(dst), DR(dst));
  373 #else /* !SLJIT_MIPS_R1 && !SLJIT_MIPS_R6 */
  374             FAIL_IF(push_inst(compiler, MULT | S(src1) | T(src2), MOVABLE_INS));
  375             return push_inst(compiler, MFLO | D(dst), DR(dst));
  376 #endif /* SLJIT_MIPS_R1 || SLJIT_MIPS_R6 */
  377         }
  378 #if (defined SLJIT_MIPS_R6 && SLJIT_MIPS_R6)
  379         FAIL_IF(push_inst(compiler, MUL | S(src1) | T(src2) | D(dst), DR(dst)));
  380         FAIL_IF(push_inst(compiler, MUH | S(src1) | T(src2) | DA(EQUAL_FLAG), EQUAL_FLAG));
  381 #else /* !SLJIT_MIPS_R6 */
  382         FAIL_IF(push_inst(compiler, MULT | S(src1) | T(src2), MOVABLE_INS));
  383         FAIL_IF(push_inst(compiler, MFHI | DA(EQUAL_FLAG), EQUAL_FLAG));
  384         FAIL_IF(push_inst(compiler, MFLO | D(dst), DR(dst)));
  385 #endif /* SLJIT_MIPS_R6 */
  386         FAIL_IF(push_inst(compiler, SRA | T(dst) | DA(OTHER_FLAG) | SH_IMM(31), OTHER_FLAG));
  387         return push_inst(compiler, SUBU | SA(EQUAL_FLAG) | TA(OTHER_FLAG) | DA(OTHER_FLAG), OTHER_FLAG);
  388 
  389     case SLJIT_AND:
  390         EMIT_LOGICAL(ANDI, AND);
  391         return SLJIT_SUCCESS;
  392 
  393     case SLJIT_OR:
  394         EMIT_LOGICAL(ORI, OR);
  395         return SLJIT_SUCCESS;
  396 
  397     case SLJIT_XOR:
  398         EMIT_LOGICAL(XORI, XOR);
  399         return SLJIT_SUCCESS;
  400 
  401     case SLJIT_SHL:
  402         EMIT_SHIFT(SLL, SLLV);
  403         return SLJIT_SUCCESS;
  404 
  405     case SLJIT_LSHR:
  406         EMIT_SHIFT(SRL, SRLV);
  407         return SLJIT_SUCCESS;
  408 
  409     case SLJIT_ASHR:
  410         EMIT_SHIFT(SRA, SRAV);
  411         return SLJIT_SUCCESS;
  412     }
  413 
  414     SLJIT_UNREACHABLE();
  415     return SLJIT_SUCCESS;
  416 }
  417 
  418 static SLJIT_INLINE sljit_s32 emit_const(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw init_value)
  419 {
  420     FAIL_IF(push_inst(compiler, LUI | T(dst) | IMM(init_value >> 16), DR(dst)));
  421     return push_inst(compiler, ORI | S(dst) | T(dst) | IMM(init_value), DR(dst));
  422 }
  423 
  424 SLJIT_API_FUNC_ATTRIBUTE void sljit_set_jump_addr(sljit_uw addr, sljit_uw new_target, sljit_sw executable_offset)
  425 {
  426     sljit_ins *inst = (sljit_ins *)addr;
  427 
  428     SLJIT_ASSERT((inst[0] & 0xffe00000) == LUI && (inst[1] & 0xfc000000) == ORI);
  429     inst[0] = (inst[0] & 0xffff0000) | ((new_target >> 16) & 0xffff);
  430     inst[1] = (inst[1] & 0xffff0000) | (new_target & 0xffff);
  431     inst = (sljit_ins *)SLJIT_ADD_EXEC_OFFSET(inst, executable_offset);
  432     SLJIT_CACHE_FLUSH(inst, inst + 2);
  433 }
  434 
  435 SLJIT_API_FUNC_ATTRIBUTE void sljit_set_const(sljit_uw addr, sljit_sw new_constant, sljit_sw executable_offset)
  436 {
  437     sljit_ins *inst = (sljit_ins *)addr;
  438 
  439     SLJIT_ASSERT((inst[0] & 0xffe00000) == LUI && (inst[1] & 0xfc000000) == ORI);
  440     inst[0] = (inst[0] & 0xffff0000) | ((new_constant >> 16) & 0xffff);
  441     inst[1] = (inst[1] & 0xffff0000) | (new_constant & 0xffff);
  442     inst = (sljit_ins *)SLJIT_ADD_EXEC_OFFSET(inst, executable_offset);
  443     SLJIT_CACHE_FLUSH(inst, inst + 2);
  444 }
  445 
  446 static sljit_s32 call_with_args(struct sljit_compiler *compiler, sljit_s32 arg_types, sljit_ins *ins_ptr)
  447 {
  448     sljit_s32 stack_offset = 0;
  449     sljit_s32 arg_count = 0;
  450     sljit_s32 float_arg_count = 0;
  451     sljit_s32 word_arg_count = 0;
  452     sljit_s32 types = 0;
  453     sljit_s32 arg_count_save, types_save;
  454     sljit_ins prev_ins = NOP;
  455     sljit_ins ins = NOP;
  456     sljit_u8 offsets[4];
  457 
  458     SLJIT_ASSERT(reg_map[TMP_REG1] == 4 && freg_map[TMP_FREG1] == 12);
  459 
  460     arg_types >>= SLJIT_DEF_SHIFT;
  461 
  462     while (arg_types) {
  463         types = (types << SLJIT_DEF_SHIFT) | (arg_types & SLJIT_DEF_MASK);
  464 
  465         switch (arg_types & SLJIT_DEF_MASK) {
  466         case SLJIT_ARG_TYPE_F32:
  467             offsets[arg_count] = (sljit_u8)stack_offset;
  468 
  469             if (word_arg_count == 0 && arg_count <= 1)
  470                 offsets[arg_count] = 254 + arg_count;
  471 
  472             stack_offset += sizeof(sljit_f32);
  473             arg_count++;
  474             float_arg_count++;
  475             break;
  476         case SLJIT_ARG_TYPE_F64:
  477             if (stack_offset & 0x7)
  478                 stack_offset += sizeof(sljit_sw);
  479             offsets[arg_count] = (sljit_u8)stack_offset;
  480 
  481             if (word_arg_count == 0 && arg_count <= 1)
  482                 offsets[arg_count] = 254 + arg_count;
  483 
  484             stack_offset += sizeof(sljit_f64);
  485             arg_count++;
  486             float_arg_count++;
  487             break;
  488         default:
  489             offsets[arg_count] = (sljit_u8)stack_offset;
  490             stack_offset += sizeof(sljit_sw);
  491             arg_count++;
  492             word_arg_count++;
  493             break;
  494         }
  495 
  496         arg_types >>= SLJIT_DEF_SHIFT;
  497     }
  498 
  499     /* Stack is aligned to 16 bytes, max two doubles can be placed on the stack. */
  500     if (stack_offset > 16)
  501         FAIL_IF(push_inst(compiler, ADDIU | S(SLJIT_SP) | T(SLJIT_SP) | IMM(-16), DR(SLJIT_SP)));
  502 
  503     types_save = types;
  504     arg_count_save = arg_count;
  505 
  506     while (types) {
  507         switch (types & SLJIT_DEF_MASK) {
  508         case SLJIT_ARG_TYPE_F32:
  509             arg_count--;
  510             if (offsets[arg_count] < 254)
  511                 ins = SWC1 | S(SLJIT_SP) | FT(float_arg_count) | IMM(offsets[arg_count]);
  512             float_arg_count--;
  513             break;
  514         case SLJIT_ARG_TYPE_F64:
  515             arg_count--;
  516             if (offsets[arg_count] < 254)
  517                 ins = SDC1 | S(SLJIT_SP) | FT(float_arg_count) | IMM(offsets[arg_count]);
  518             float_arg_count--;
  519             break;
  520         default:
  521             if (offsets[arg_count - 1] >= 16)
  522                 ins = SW | S(SLJIT_SP) | T(word_arg_count) | IMM(offsets[arg_count - 1]);
  523             else if (arg_count != word_arg_count)
  524                 ins = ADDU | S(word_arg_count) | TA(0) | DA(4 + (offsets[arg_count - 1] >> 2));
  525             else if (arg_count == 1)
  526                 ins = ADDU | S(SLJIT_R0) | TA(0) | DA(4);
  527 
  528             arg_count--;
  529             word_arg_count--;
  530             break;
  531         }
  532 
  533         if (ins != NOP) {
  534             if (prev_ins != NOP)
  535                 FAIL_IF(push_inst(compiler, prev_ins, MOVABLE_INS));
  536             prev_ins = ins;
  537             ins = NOP;
  538         }
  539 
  540         types >>= SLJIT_DEF_SHIFT;
  541     }
  542 
  543     types = types_save;
  544     arg_count = arg_count_save;
  545 
  546     while (types) {
  547         switch (types & SLJIT_DEF_MASK) {
  548         case SLJIT_ARG_TYPE_F32:
  549             arg_count--;
  550             if (offsets[arg_count] == 254)
  551                 ins = MOV_S | FMT_S | FS(SLJIT_FR0) | FD(TMP_FREG1);
  552             else if (offsets[arg_count] < 16)
  553                 ins = LW | S(SLJIT_SP) | TA(4 + (offsets[arg_count] >> 2)) | IMM(offsets[arg_count]);
  554             break;
  555         case SLJIT_ARG_TYPE_F64:
  556             arg_count--;
  557             if (offsets[arg_count] == 254)
  558                 ins = MOV_S | FMT_D | FS(SLJIT_FR0) | FD(TMP_FREG1);
  559             else if (offsets[arg_count] < 16) {
  560                 if (prev_ins != NOP)
  561                     FAIL_IF(push_inst(compiler, prev_ins, MOVABLE_INS));
  562                 prev_ins = LW | S(SLJIT_SP) | TA(4 + (offsets[arg_count] >> 2)) | IMM(offsets[arg_count]);
  563                 ins = LW | S(SLJIT_SP) | TA(5 + (offsets[arg_count] >> 2)) | IMM(offsets[arg_count] + sizeof(sljit_sw));
  564             }
  565             break;
  566         default:
  567             arg_count--;
  568             break;
  569         }
  570 
  571         if (ins != NOP) {
  572             if (prev_ins != NOP)
  573                 FAIL_IF(push_inst(compiler, prev_ins, MOVABLE_INS));
  574             prev_ins = ins;
  575             ins = NOP;
  576         }
  577 
  578         types >>= SLJIT_DEF_SHIFT;
  579     }
  580 
  581     *ins_ptr = prev_ins;
  582 
  583     return SLJIT_SUCCESS;
  584 }
  585 
  586 static sljit_s32 post_call_with_args(struct sljit_compiler *compiler, sljit_s32 arg_types)
  587 {
  588     sljit_s32 stack_offset = 0;
  589 
  590     arg_types >>= SLJIT_DEF_SHIFT;
  591 
  592     while (arg_types) {
  593         switch (arg_types & SLJIT_DEF_MASK) {
  594         case SLJIT_ARG_TYPE_F32:
  595             stack_offset += sizeof(sljit_f32);
  596             break;
  597         case SLJIT_ARG_TYPE_F64:
  598             if (stack_offset & 0x7)
  599                 stack_offset += sizeof(sljit_sw);
  600             stack_offset += sizeof(sljit_f64);
  601             break;
  602         default:
  603             stack_offset += sizeof(sljit_sw);
  604             break;
  605         }
  606 
  607         arg_types >>= SLJIT_DEF_SHIFT;
  608     }
  609 
  610     /* Stack is aligned to 16 bytes, max two doubles can be placed on the stack. */
  611     if (stack_offset > 16)
  612         return push_inst(compiler, ADDIU | S(SLJIT_SP) | T(SLJIT_SP) | IMM(16), DR(SLJIT_SP));
  613 
  614     return SLJIT_SUCCESS;
  615 }
  616 
  617 SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_call(struct sljit_compiler *compiler, sljit_s32 type,
  618     sljit_s32 arg_types)
  619 {
  620     struct sljit_jump *jump;
  621     sljit_ins ins;
  622 
  623     CHECK_ERROR_PTR();
  624     CHECK_PTR(check_sljit_emit_call(compiler, type, arg_types));
  625 
  626     jump = (struct sljit_jump*)ensure_abuf(compiler, sizeof(struct sljit_jump));
  627     PTR_FAIL_IF(!jump);
  628     set_jump(jump, compiler, type & SLJIT_REWRITABLE_JUMP);
  629     type &= 0xff;
  630 
  631     PTR_FAIL_IF(call_with_args(compiler, arg_types, &ins));
  632 
  633     SLJIT_ASSERT(DR(PIC_ADDR_REG) == 25 && PIC_ADDR_REG == TMP_REG2);
  634 
  635     PTR_FAIL_IF(emit_const(compiler, PIC_ADDR_REG, 0));
  636 
  637     jump->flags |= IS_JAL | IS_CALL;
  638     PTR_FAIL_IF(push_inst(compiler, JALR | S(PIC_ADDR_REG) | DA(RETURN_ADDR_REG), UNMOVABLE_INS));
  639     jump->addr = compiler->size;
  640     PTR_FAIL_IF(push_inst(compiler, ins, UNMOVABLE_INS));
  641 
  642     PTR_FAIL_IF(post_call_with_args(compiler, arg_types));
  643 
  644     return jump;
  645 }
  646 
  647 SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_icall(struct sljit_compiler *compiler, sljit_s32 type,
  648     sljit_s32 arg_types,
  649     sljit_s32 src, sljit_sw srcw)
  650 {
  651     sljit_ins ins;
  652 
  653     CHECK_ERROR();
  654     CHECK(check_sljit_emit_icall(compiler, type, arg_types, src, srcw));
  655 
  656     SLJIT_ASSERT(DR(PIC_ADDR_REG) == 25 && PIC_ADDR_REG == TMP_REG2);
  657 
  658     if (src & SLJIT_IMM)
  659         FAIL_IF(load_immediate(compiler, DR(PIC_ADDR_REG), srcw));
  660     else if (FAST_IS_REG(src))
  661         FAIL_IF(push_inst(compiler, ADDU | S(src) | TA(0) | D(PIC_ADDR_REG), DR(PIC_ADDR_REG)));
  662     else if (src & SLJIT_MEM) {
  663         ADJUST_LOCAL_OFFSET(src, srcw);
  664         FAIL_IF(emit_op_mem(compiler, WORD_DATA | LOAD_DATA, DR(PIC_ADDR_REG), src, srcw));
  665     }
  666 
  667     FAIL_IF(call_with_args(compiler, arg_types, &ins));
  668 
  669     /* Register input. */
  670     FAIL_IF(push_inst(compiler, JALR | S(PIC_ADDR_REG) | DA(RETURN_ADDR_REG), UNMOVABLE_INS));
  671     FAIL_IF(push_inst(compiler, ins, UNMOVABLE_INS));
  672     return post_call_with_args(compiler, arg_types);
  673 }