"Fossies" - the Fresh Open Source Software Archive

Member "pcre-8.43/sljit/sljitNativeMIPS_32.c" (19 Mar 2018, 23893 Bytes) of package /linux/misc/pcre-8.43.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 last Fossies "Diffs" side-by-side code changes report: 8.41_vs_8.42.

    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)
  372             return push_inst(compiler, MUL | S(src1) | T(src2) | D(dst), DR(dst));
  373 #else
  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
  377         }
  378         FAIL_IF(push_inst(compiler, MULT | S(src1) | T(src2), MOVABLE_INS));
  379         FAIL_IF(push_inst(compiler, MFHI | DA(EQUAL_FLAG), EQUAL_FLAG));
  380         FAIL_IF(push_inst(compiler, MFLO | D(dst), DR(dst)));
  381         FAIL_IF(push_inst(compiler, SRA | T(dst) | DA(OTHER_FLAG) | SH_IMM(31), OTHER_FLAG));
  382         return push_inst(compiler, SUBU | SA(EQUAL_FLAG) | TA(OTHER_FLAG) | DA(OTHER_FLAG), OTHER_FLAG);
  383 
  384     case SLJIT_AND:
  385         EMIT_LOGICAL(ANDI, AND);
  386         return SLJIT_SUCCESS;
  387 
  388     case SLJIT_OR:
  389         EMIT_LOGICAL(ORI, OR);
  390         return SLJIT_SUCCESS;
  391 
  392     case SLJIT_XOR:
  393         EMIT_LOGICAL(XORI, XOR);
  394         return SLJIT_SUCCESS;
  395 
  396     case SLJIT_SHL:
  397         EMIT_SHIFT(SLL, SLLV);
  398         return SLJIT_SUCCESS;
  399 
  400     case SLJIT_LSHR:
  401         EMIT_SHIFT(SRL, SRLV);
  402         return SLJIT_SUCCESS;
  403 
  404     case SLJIT_ASHR:
  405         EMIT_SHIFT(SRA, SRAV);
  406         return SLJIT_SUCCESS;
  407     }
  408 
  409     SLJIT_UNREACHABLE();
  410     return SLJIT_SUCCESS;
  411 }
  412 
  413 static SLJIT_INLINE sljit_s32 emit_const(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw init_value)
  414 {
  415     FAIL_IF(push_inst(compiler, LUI | T(dst) | IMM(init_value >> 16), DR(dst)));
  416     return push_inst(compiler, ORI | S(dst) | T(dst) | IMM(init_value), DR(dst));
  417 }
  418 
  419 SLJIT_API_FUNC_ATTRIBUTE void sljit_set_jump_addr(sljit_uw addr, sljit_uw new_target, sljit_sw executable_offset)
  420 {
  421     sljit_ins *inst = (sljit_ins *)addr;
  422 
  423     inst[0] = (inst[0] & 0xffff0000) | ((new_target >> 16) & 0xffff);
  424     inst[1] = (inst[1] & 0xffff0000) | (new_target & 0xffff);
  425     inst = (sljit_ins *)SLJIT_ADD_EXEC_OFFSET(inst, executable_offset);
  426     SLJIT_CACHE_FLUSH(inst, inst + 2);
  427 }
  428 
  429 SLJIT_API_FUNC_ATTRIBUTE void sljit_set_const(sljit_uw addr, sljit_sw new_constant, sljit_sw executable_offset)
  430 {
  431     sljit_ins *inst = (sljit_ins *)addr;
  432 
  433     inst[0] = (inst[0] & 0xffff0000) | ((new_constant >> 16) & 0xffff);
  434     inst[1] = (inst[1] & 0xffff0000) | (new_constant & 0xffff);
  435     inst = (sljit_ins *)SLJIT_ADD_EXEC_OFFSET(inst, executable_offset);
  436     SLJIT_CACHE_FLUSH(inst, inst + 2);
  437 }
  438 
  439 static sljit_s32 call_with_args(struct sljit_compiler *compiler, sljit_s32 arg_types, sljit_ins *ins_ptr)
  440 {
  441     sljit_s32 stack_offset = 0;
  442     sljit_s32 arg_count = 0;
  443     sljit_s32 float_arg_count = 0;
  444     sljit_s32 word_arg_count = 0;
  445     sljit_s32 types = 0;
  446     sljit_s32 arg_count_save, types_save;
  447     sljit_ins prev_ins = NOP;
  448     sljit_ins ins = NOP;
  449     sljit_u8 offsets[4];
  450 
  451     SLJIT_ASSERT(reg_map[TMP_REG1] == 4 && freg_map[TMP_FREG1] == 12);
  452 
  453     arg_types >>= SLJIT_DEF_SHIFT;
  454 
  455     while (arg_types) {
  456         types = (types << SLJIT_DEF_SHIFT) | (arg_types & SLJIT_DEF_MASK);
  457 
  458         switch (arg_types & SLJIT_DEF_MASK) {
  459         case SLJIT_ARG_TYPE_F32:
  460             offsets[arg_count] = (sljit_u8)stack_offset;
  461 
  462             if (word_arg_count == 0 && arg_count <= 1)
  463                 offsets[arg_count] = 254 + arg_count;
  464 
  465             stack_offset += sizeof(sljit_f32);
  466             arg_count++;
  467             float_arg_count++;
  468             break;
  469         case SLJIT_ARG_TYPE_F64:
  470             if (stack_offset & 0x7)
  471                 stack_offset += sizeof(sljit_sw);
  472             offsets[arg_count] = (sljit_u8)stack_offset;
  473 
  474             if (word_arg_count == 0 && arg_count <= 1)
  475                 offsets[arg_count] = 254 + arg_count;
  476 
  477             stack_offset += sizeof(sljit_f64);
  478             arg_count++;
  479             float_arg_count++;
  480             break;
  481         default:
  482             offsets[arg_count] = (sljit_u8)stack_offset;
  483             stack_offset += sizeof(sljit_sw);
  484             arg_count++;
  485             word_arg_count++;
  486             break;
  487         }
  488 
  489         arg_types >>= SLJIT_DEF_SHIFT;
  490     }
  491 
  492     /* Stack is aligned to 16 bytes, max two doubles can be placed on the stack. */
  493     if (stack_offset > 16)
  494         FAIL_IF(push_inst(compiler, ADDIU | S(SLJIT_SP) | T(SLJIT_SP) | IMM(-16), DR(SLJIT_SP)));
  495 
  496     types_save = types;
  497     arg_count_save = arg_count;
  498 
  499     while (types) {
  500         switch (types & SLJIT_DEF_MASK) {
  501         case SLJIT_ARG_TYPE_F32:
  502             arg_count--;
  503             if (offsets[arg_count] < 254)
  504                 ins = SWC1 | S(SLJIT_SP) | FT(float_arg_count) | IMM(offsets[arg_count]);
  505             float_arg_count--;
  506             break;
  507         case SLJIT_ARG_TYPE_F64:
  508             arg_count--;
  509             if (offsets[arg_count] < 254)
  510                 ins = SDC1 | S(SLJIT_SP) | FT(float_arg_count) | IMM(offsets[arg_count]);
  511             float_arg_count--;
  512             break;
  513         default:
  514             if (offsets[arg_count - 1] >= 16)
  515                 ins = SW | S(SLJIT_SP) | T(word_arg_count) | IMM(offsets[arg_count - 1]);
  516             else if (arg_count != word_arg_count)
  517                 ins = ADDU | S(word_arg_count) | TA(0) | DA(4 + (offsets[arg_count - 1] >> 2));
  518             else if (arg_count == 1)
  519                 ins = ADDU | S(SLJIT_R0) | TA(0) | DA(4);
  520 
  521             arg_count--;
  522             word_arg_count--;
  523             break;
  524         }
  525 
  526         if (ins != NOP) {
  527             if (prev_ins != NOP)
  528                 FAIL_IF(push_inst(compiler, prev_ins, MOVABLE_INS));
  529             prev_ins = ins;
  530             ins = NOP;
  531         }
  532 
  533         types >>= SLJIT_DEF_SHIFT;
  534     }
  535 
  536     types = types_save;
  537     arg_count = arg_count_save;
  538 
  539     while (types) {
  540         switch (types & SLJIT_DEF_MASK) {
  541         case SLJIT_ARG_TYPE_F32:
  542             arg_count--;
  543             if (offsets[arg_count] == 254)
  544                 ins = MOV_S | FMT_S | FS(SLJIT_FR0) | FD(TMP_FREG1);
  545             else if (offsets[arg_count] < 16)
  546                 ins = LW | S(SLJIT_SP) | TA(4 + (offsets[arg_count] >> 2)) | IMM(offsets[arg_count]);
  547             break;
  548         case SLJIT_ARG_TYPE_F64:
  549             arg_count--;
  550             if (offsets[arg_count] == 254)
  551                 ins = MOV_S | FMT_D | FS(SLJIT_FR0) | FD(TMP_FREG1);
  552             else if (offsets[arg_count] < 16) {
  553                 if (prev_ins != NOP)
  554                     FAIL_IF(push_inst(compiler, prev_ins, MOVABLE_INS));
  555                 prev_ins = LW | S(SLJIT_SP) | TA(4 + (offsets[arg_count] >> 2)) | IMM(offsets[arg_count]);
  556                 ins = LW | S(SLJIT_SP) | TA(5 + (offsets[arg_count] >> 2)) | IMM(offsets[arg_count] + sizeof(sljit_sw));
  557             }
  558             break;
  559         default:
  560             arg_count--;
  561             break;
  562         }
  563 
  564         if (ins != NOP) {
  565             if (prev_ins != NOP)
  566                 FAIL_IF(push_inst(compiler, prev_ins, MOVABLE_INS));
  567             prev_ins = ins;
  568             ins = NOP;
  569         }
  570 
  571         types >>= SLJIT_DEF_SHIFT;
  572     }
  573 
  574     *ins_ptr = prev_ins;
  575 
  576     return SLJIT_SUCCESS;
  577 }
  578 
  579 static sljit_s32 post_call_with_args(struct sljit_compiler *compiler, sljit_s32 arg_types)
  580 {
  581     sljit_s32 stack_offset = 0;
  582 
  583     arg_types >>= SLJIT_DEF_SHIFT;
  584 
  585     while (arg_types) {
  586         switch (arg_types & SLJIT_DEF_MASK) {
  587         case SLJIT_ARG_TYPE_F32:
  588             stack_offset += sizeof(sljit_f32);
  589             break;
  590         case SLJIT_ARG_TYPE_F64:
  591             if (stack_offset & 0x7)
  592                 stack_offset += sizeof(sljit_sw);
  593             stack_offset += sizeof(sljit_f64);
  594             break;
  595         default:
  596             stack_offset += sizeof(sljit_sw);
  597             break;
  598         }
  599 
  600         arg_types >>= SLJIT_DEF_SHIFT;
  601     }
  602 
  603     /* Stack is aligned to 16 bytes, max two doubles can be placed on the stack. */
  604     if (stack_offset > 16)
  605         return push_inst(compiler, ADDIU | S(SLJIT_SP) | T(SLJIT_SP) | IMM(16), DR(SLJIT_SP));
  606 
  607     return SLJIT_SUCCESS;
  608 }
  609 
  610 SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_call(struct sljit_compiler *compiler, sljit_s32 type,
  611     sljit_s32 arg_types)
  612 {
  613     struct sljit_jump *jump;
  614     sljit_ins ins;
  615 
  616     CHECK_ERROR_PTR();
  617     CHECK_PTR(check_sljit_emit_call(compiler, type, arg_types));
  618 
  619     jump = (struct sljit_jump*)ensure_abuf(compiler, sizeof(struct sljit_jump));
  620     PTR_FAIL_IF(!jump);
  621     set_jump(jump, compiler, type & SLJIT_REWRITABLE_JUMP);
  622     type &= 0xff;
  623 
  624     PTR_FAIL_IF(call_with_args(compiler, arg_types, &ins));
  625 
  626     SLJIT_ASSERT(DR(PIC_ADDR_REG) == 25 && PIC_ADDR_REG == TMP_REG2);
  627 
  628     PTR_FAIL_IF(emit_const(compiler, PIC_ADDR_REG, 0));
  629 
  630     jump->flags |= IS_JAL | IS_CALL;
  631     PTR_FAIL_IF(push_inst(compiler, JALR | S(PIC_ADDR_REG) | DA(RETURN_ADDR_REG), UNMOVABLE_INS));
  632     jump->addr = compiler->size;
  633     PTR_FAIL_IF(push_inst(compiler, ins, UNMOVABLE_INS));
  634 
  635     PTR_FAIL_IF(post_call_with_args(compiler, arg_types));
  636 
  637     return jump;
  638 }
  639 
  640 SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_icall(struct sljit_compiler *compiler, sljit_s32 type,
  641     sljit_s32 arg_types,
  642     sljit_s32 src, sljit_sw srcw)
  643 {
  644     sljit_ins ins;
  645 
  646     CHECK_ERROR();
  647     CHECK(check_sljit_emit_icall(compiler, type, arg_types, src, srcw));
  648 
  649     SLJIT_ASSERT(DR(PIC_ADDR_REG) == 25 && PIC_ADDR_REG == TMP_REG2);
  650 
  651     if (src & SLJIT_IMM)
  652         FAIL_IF(load_immediate(compiler, DR(PIC_ADDR_REG), srcw));
  653     else if (FAST_IS_REG(src))
  654         FAIL_IF(push_inst(compiler, ADDU | S(src) | TA(0) | D(PIC_ADDR_REG), DR(PIC_ADDR_REG)));
  655     else if (src & SLJIT_MEM) {
  656         ADJUST_LOCAL_OFFSET(src, srcw);
  657         FAIL_IF(emit_op_mem(compiler, WORD_DATA | LOAD_DATA, DR(PIC_ADDR_REG), src, srcw));
  658     }
  659 
  660     FAIL_IF(call_with_args(compiler, arg_types, &ins));
  661 
  662     /* Register input. */
  663     FAIL_IF(push_inst(compiler, JALR | S(PIC_ADDR_REG) | DA(RETURN_ADDR_REG), UNMOVABLE_INS));
  664     FAIL_IF(push_inst(compiler, ins, UNMOVABLE_INS));
  665     return post_call_with_args(compiler, arg_types);
  666 }