"Fossies" - the Fresh Open Source Software Archive

Member "pcre-8.42/sljit/sljitNativeMIPS_64.c" (19 Mar 2018, 24979 Bytes) of package /linux/misc/pcre-8.42.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_64.c" see the Fossies "Dox" file reference documentation and the latest 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 64-bit arch dependent functions. */
   28 
   29 static sljit_s32 load_immediate(struct sljit_compiler *compiler, sljit_s32 dst_ar, sljit_sw imm)
   30 {
   31     sljit_s32 shift = 32;
   32     sljit_s32 shift2;
   33     sljit_s32 inv = 0;
   34     sljit_ins ins;
   35     sljit_uw uimm;
   36 
   37     if (!(imm & ~0xffff))
   38         return push_inst(compiler, ORI | SA(0) | TA(dst_ar) | IMM(imm), dst_ar);
   39 
   40     if (imm < 0 && imm >= SIMM_MIN)
   41         return push_inst(compiler, ADDIU | SA(0) | TA(dst_ar) | IMM(imm), dst_ar);
   42 
   43     if (imm <= 0x7fffffffl && imm >= -0x80000000l) {
   44         FAIL_IF(push_inst(compiler, LUI | TA(dst_ar) | IMM(imm >> 16), dst_ar));
   45         return (imm & 0xffff) ? push_inst(compiler, ORI | SA(dst_ar) | TA(dst_ar) | IMM(imm), dst_ar) : SLJIT_SUCCESS;
   46     }
   47 
   48     /* Zero extended number. */
   49     uimm = imm;
   50     if (imm < 0) {
   51         uimm = ~imm;
   52         inv = 1;
   53     }
   54 
   55     while (!(uimm & 0xff00000000000000l)) {
   56         shift -= 8;
   57         uimm <<= 8;
   58     }
   59 
   60     if (!(uimm & 0xf000000000000000l)) {
   61         shift -= 4;
   62         uimm <<= 4;
   63     }
   64 
   65     if (!(uimm & 0xc000000000000000l)) {
   66         shift -= 2;
   67         uimm <<= 2;
   68     }
   69 
   70     if ((sljit_sw)uimm < 0) {
   71         uimm >>= 1;
   72         shift += 1;
   73     }
   74     SLJIT_ASSERT(((uimm & 0xc000000000000000l) == 0x4000000000000000l) && (shift > 0) && (shift <= 32));
   75 
   76     if (inv)
   77         uimm = ~uimm;
   78 
   79     FAIL_IF(push_inst(compiler, LUI | TA(dst_ar) | IMM(uimm >> 48), dst_ar));
   80     if (uimm & 0x0000ffff00000000l)
   81         FAIL_IF(push_inst(compiler, ORI | SA(dst_ar) | TA(dst_ar) | IMM(uimm >> 32), dst_ar));
   82 
   83     imm &= (1l << shift) - 1;
   84     if (!(imm & ~0xffff)) {
   85         ins = (shift == 32) ? DSLL32 : DSLL;
   86         if (shift < 32)
   87             ins |= SH_IMM(shift);
   88         FAIL_IF(push_inst(compiler, ins | TA(dst_ar) | DA(dst_ar), dst_ar));
   89         return !(imm & 0xffff) ? SLJIT_SUCCESS : push_inst(compiler, ORI | SA(dst_ar) | TA(dst_ar) | IMM(imm), dst_ar);
   90     }
   91 
   92     /* Double shifts needs to be performed. */
   93     uimm <<= 32;
   94     shift2 = shift - 16;
   95 
   96     while (!(uimm & 0xf000000000000000l)) {
   97         shift2 -= 4;
   98         uimm <<= 4;
   99     }
  100 
  101     if (!(uimm & 0xc000000000000000l)) {
  102         shift2 -= 2;
  103         uimm <<= 2;
  104     }
  105 
  106     if (!(uimm & 0x8000000000000000l)) {
  107         shift2--;
  108         uimm <<= 1;
  109     }
  110 
  111     SLJIT_ASSERT((uimm & 0x8000000000000000l) && (shift2 > 0) && (shift2 <= 16));
  112 
  113     FAIL_IF(push_inst(compiler, DSLL | TA(dst_ar) | DA(dst_ar) | SH_IMM(shift - shift2), dst_ar));
  114     FAIL_IF(push_inst(compiler, ORI | SA(dst_ar) | TA(dst_ar) | IMM(uimm >> 48), dst_ar));
  115     FAIL_IF(push_inst(compiler, DSLL | TA(dst_ar) | DA(dst_ar) | SH_IMM(shift2), dst_ar));
  116 
  117     imm &= (1l << shift2) - 1;
  118     return !(imm & 0xffff) ? SLJIT_SUCCESS : push_inst(compiler, ORI | SA(dst_ar) | TA(dst_ar) | IMM(imm), dst_ar);
  119 }
  120 
  121 #define SELECT_OP(a, b) \
  122     (!(op & SLJIT_I32_OP) ? a : b)
  123 
  124 #define EMIT_LOGICAL(op_imm, op_norm) \
  125     if (flags & SRC2_IMM) { \
  126         if (op & SLJIT_SET_Z) \
  127             FAIL_IF(push_inst(compiler, op_imm | S(src1) | TA(EQUAL_FLAG) | IMM(src2), EQUAL_FLAG)); \
  128         if (!(flags & UNUSED_DEST)) \
  129             FAIL_IF(push_inst(compiler, op_imm | S(src1) | T(dst) | IMM(src2), DR(dst))); \
  130     } \
  131     else { \
  132         if (op & SLJIT_SET_Z) \
  133             FAIL_IF(push_inst(compiler, op_norm | S(src1) | T(src2) | DA(EQUAL_FLAG), EQUAL_FLAG)); \
  134         if (!(flags & UNUSED_DEST)) \
  135             FAIL_IF(push_inst(compiler, op_norm | S(src1) | T(src2) | D(dst), DR(dst))); \
  136     }
  137 
  138 #define EMIT_SHIFT(op_dimm, op_dimm32, op_imm, op_dv, op_v) \
  139     if (flags & SRC2_IMM) { \
  140         if (src2 >= 32) { \
  141             SLJIT_ASSERT(!(op & SLJIT_I32_OP)); \
  142             ins = op_dimm32; \
  143             src2 -= 32; \
  144         } \
  145         else \
  146             ins = (op & SLJIT_I32_OP) ? op_imm : op_dimm; \
  147         if (op & SLJIT_SET_Z) \
  148             FAIL_IF(push_inst(compiler, ins | T(src1) | DA(EQUAL_FLAG) | SH_IMM(src2), EQUAL_FLAG)); \
  149         if (!(flags & UNUSED_DEST)) \
  150             FAIL_IF(push_inst(compiler, ins | T(src1) | D(dst) | SH_IMM(src2), DR(dst))); \
  151     } \
  152     else { \
  153         ins = (op & SLJIT_I32_OP) ? op_v : op_dv; \
  154         if (op & SLJIT_SET_Z) \
  155             FAIL_IF(push_inst(compiler, ins | S(src2) | T(src1) | DA(EQUAL_FLAG), EQUAL_FLAG)); \
  156         if (!(flags & UNUSED_DEST)) \
  157             FAIL_IF(push_inst(compiler, ins | S(src2) | T(src1) | D(dst), DR(dst))); \
  158     }
  159 
  160 static SLJIT_INLINE sljit_s32 emit_single_op(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 flags,
  161     sljit_s32 dst, sljit_s32 src1, sljit_sw src2)
  162 {
  163     sljit_ins ins;
  164     sljit_s32 is_overflow, is_carry, is_handled;
  165 
  166     switch (GET_OPCODE(op)) {
  167     case SLJIT_MOV:
  168     case SLJIT_MOV_P:
  169         SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & SRC2_IMM));
  170         if (dst != src2)
  171             return push_inst(compiler, SELECT_OP(DADDU, ADDU) | S(src2) | TA(0) | D(dst), DR(dst));
  172         return SLJIT_SUCCESS;
  173 
  174     case SLJIT_MOV_U8:
  175     case SLJIT_MOV_S8:
  176         SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & SRC2_IMM));
  177         if ((flags & (REG_DEST | REG2_SOURCE)) == (REG_DEST | REG2_SOURCE)) {
  178             if (op == SLJIT_MOV_S8) {
  179                 FAIL_IF(push_inst(compiler, DSLL32 | T(src2) | D(dst) | SH_IMM(24), DR(dst)));
  180                 return push_inst(compiler, DSRA32 | T(dst) | D(dst) | SH_IMM(24), DR(dst));
  181             }
  182             return push_inst(compiler, ANDI | S(src2) | T(dst) | IMM(0xff), DR(dst));
  183         }
  184         else {
  185             SLJIT_ASSERT(dst == src2);
  186         }
  187         return SLJIT_SUCCESS;
  188 
  189     case SLJIT_MOV_U16:
  190     case SLJIT_MOV_S16:
  191         SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & SRC2_IMM));
  192         if ((flags & (REG_DEST | REG2_SOURCE)) == (REG_DEST | REG2_SOURCE)) {
  193             if (op == SLJIT_MOV_S16) {
  194                 FAIL_IF(push_inst(compiler, DSLL32 | T(src2) | D(dst) | SH_IMM(16), DR(dst)));
  195                 return push_inst(compiler, DSRA32 | T(dst) | D(dst) | SH_IMM(16), DR(dst));
  196             }
  197             return push_inst(compiler, ANDI | S(src2) | T(dst) | IMM(0xffff), DR(dst));
  198         }
  199         else {
  200             SLJIT_ASSERT(dst == src2);
  201         }
  202         return SLJIT_SUCCESS;
  203 
  204     case SLJIT_MOV_U32:
  205         SLJIT_ASSERT(!(op & SLJIT_I32_OP));
  206         FAIL_IF(push_inst(compiler, DSLL32 | T(src2) | D(dst) | SH_IMM(0), DR(dst)));
  207         return push_inst(compiler, DSRL32 | T(dst) | D(dst) | SH_IMM(0), DR(dst));
  208 
  209     case SLJIT_MOV_S32:
  210         SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & SRC2_IMM));
  211         return push_inst(compiler, SLL | T(src2) | D(dst) | SH_IMM(0), DR(dst));
  212 
  213     case SLJIT_NOT:
  214         SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & SRC2_IMM));
  215         if (op & SLJIT_SET_Z)
  216             FAIL_IF(push_inst(compiler, NOR | S(src2) | T(src2) | DA(EQUAL_FLAG), EQUAL_FLAG));
  217         if (!(flags & UNUSED_DEST))
  218             FAIL_IF(push_inst(compiler, NOR | S(src2) | T(src2) | D(dst), DR(dst)));
  219         return SLJIT_SUCCESS;
  220 
  221     case SLJIT_CLZ:
  222         SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & SRC2_IMM));
  223 #if (defined SLJIT_MIPS_R1 && SLJIT_MIPS_R1)
  224         if (op & SLJIT_SET_Z)
  225             FAIL_IF(push_inst(compiler, SELECT_OP(DCLZ, CLZ) | S(src2) | TA(EQUAL_FLAG) | DA(EQUAL_FLAG), EQUAL_FLAG));
  226         if (!(flags & UNUSED_DEST))
  227             FAIL_IF(push_inst(compiler, SELECT_OP(DCLZ, CLZ) | S(src2) | T(dst) | D(dst), DR(dst)));
  228 #else
  229         if (SLJIT_UNLIKELY(flags & UNUSED_DEST)) {
  230             FAIL_IF(push_inst(compiler, SELECT_OP(DSRL32, SRL) | T(src2) | DA(EQUAL_FLAG) | SH_IMM(31), EQUAL_FLAG));
  231             return push_inst(compiler, XORI | SA(EQUAL_FLAG) | TA(EQUAL_FLAG) | IMM(1), EQUAL_FLAG);
  232         }
  233         /* Nearly all instructions are unmovable in the following sequence. */
  234         FAIL_IF(push_inst(compiler, SELECT_OP(DADDU, ADDU) | S(src2) | TA(0) | D(TMP_REG1), DR(TMP_REG1)));
  235         /* Check zero. */
  236         FAIL_IF(push_inst(compiler, BEQ | S(TMP_REG1) | TA(0) | IMM(5), UNMOVABLE_INS));
  237         FAIL_IF(push_inst(compiler, ORI | SA(0) | T(dst) | IMM((op & SLJIT_I32_OP) ? 32 : 64), UNMOVABLE_INS));
  238         FAIL_IF(push_inst(compiler, SELECT_OP(DADDIU, ADDIU) | SA(0) | T(dst) | IMM(-1), DR(dst)));
  239         /* Loop for searching the highest bit. */
  240         FAIL_IF(push_inst(compiler, SELECT_OP(DADDIU, ADDIU) | S(dst) | T(dst) | IMM(1), DR(dst)));
  241         FAIL_IF(push_inst(compiler, BGEZ | S(TMP_REG1) | IMM(-2), UNMOVABLE_INS));
  242         FAIL_IF(push_inst(compiler, SELECT_OP(DSLL, SLL) | T(TMP_REG1) | D(TMP_REG1) | SH_IMM(1), UNMOVABLE_INS));
  243 #endif
  244         return SLJIT_SUCCESS;
  245 
  246     case SLJIT_ADD:
  247         is_overflow = GET_FLAG_TYPE(op) == SLJIT_OVERFLOW;
  248         is_carry = GET_FLAG_TYPE(op) == GET_FLAG_TYPE(SLJIT_SET_CARRY);
  249 
  250         if (flags & SRC2_IMM) {
  251             if (is_overflow) {
  252                 if (src2 >= 0)
  253                     FAIL_IF(push_inst(compiler, OR | S(src1) | T(src1) | DA(EQUAL_FLAG), EQUAL_FLAG));
  254                 else
  255                     FAIL_IF(push_inst(compiler, NOR | S(src1) | T(src1) | DA(EQUAL_FLAG), EQUAL_FLAG));
  256             }
  257             else if (op & SLJIT_SET_Z)
  258                 FAIL_IF(push_inst(compiler, SELECT_OP(DADDIU, ADDIU) | S(src1) | TA(EQUAL_FLAG) | IMM(src2), EQUAL_FLAG));
  259 
  260             if (is_overflow || is_carry) {
  261                 if (src2 >= 0)
  262                     FAIL_IF(push_inst(compiler, ORI | S(src1) | TA(OTHER_FLAG) | IMM(src2), OTHER_FLAG));
  263                 else {
  264                     FAIL_IF(push_inst(compiler, SELECT_OP(DADDIU, ADDIU) | SA(0) | TA(OTHER_FLAG) | IMM(src2), OTHER_FLAG));
  265                     FAIL_IF(push_inst(compiler, OR | S(src1) | TA(OTHER_FLAG) | DA(OTHER_FLAG), OTHER_FLAG));
  266                 }
  267             }
  268             /* dst may be the same as src1 or src2. */
  269             if (!(flags & UNUSED_DEST) || (op & VARIABLE_FLAG_MASK))
  270                 FAIL_IF(push_inst(compiler, SELECT_OP(DADDIU, ADDIU) | S(src1) | T(dst) | IMM(src2), DR(dst)));
  271         }
  272         else {
  273             if (is_overflow)
  274                 FAIL_IF(push_inst(compiler, XOR | S(src1) | T(src2) | DA(EQUAL_FLAG), EQUAL_FLAG));
  275             else if (op & SLJIT_SET_Z)
  276                 FAIL_IF(push_inst(compiler, SELECT_OP(DADDU, ADDU) | S(src1) | T(src2) | DA(EQUAL_FLAG), EQUAL_FLAG));
  277 
  278             if (is_overflow || is_carry)
  279                 FAIL_IF(push_inst(compiler, OR | S(src1) | T(src2) | DA(OTHER_FLAG), OTHER_FLAG));
  280             /* dst may be the same as src1 or src2. */
  281             if (!(flags & UNUSED_DEST) || (op & VARIABLE_FLAG_MASK))
  282                 FAIL_IF(push_inst(compiler, SELECT_OP(DADDU, ADDU) | S(src1) | T(src2) | D(dst), DR(dst)));
  283         }
  284 
  285         /* a + b >= a | b (otherwise, the carry should be set to 1). */
  286         if (is_overflow || is_carry)
  287             FAIL_IF(push_inst(compiler, SLTU | S(dst) | TA(OTHER_FLAG) | DA(OTHER_FLAG), OTHER_FLAG));
  288         if (!is_overflow)
  289             return SLJIT_SUCCESS;
  290         FAIL_IF(push_inst(compiler, SELECT_OP(DSLL32, SLL) | TA(OTHER_FLAG) | D(TMP_REG1) | SH_IMM(31), DR(TMP_REG1)));
  291         FAIL_IF(push_inst(compiler, XOR | S(TMP_REG1) | TA(EQUAL_FLAG) | DA(EQUAL_FLAG), EQUAL_FLAG));
  292         FAIL_IF(push_inst(compiler, XOR | S(dst) | TA(EQUAL_FLAG) | DA(OTHER_FLAG), OTHER_FLAG));
  293         if (op & SLJIT_SET_Z)
  294             FAIL_IF(push_inst(compiler, SELECT_OP(DADDU, ADDU) | S(dst) | TA(0) | DA(EQUAL_FLAG), EQUAL_FLAG));
  295         return push_inst(compiler, SELECT_OP(DSRL32, SRL) | TA(OTHER_FLAG) | DA(OTHER_FLAG) | SH_IMM(31), OTHER_FLAG);
  296 
  297     case SLJIT_ADDC:
  298         is_carry = GET_FLAG_TYPE(op) == GET_FLAG_TYPE(SLJIT_SET_CARRY);
  299 
  300         if (flags & SRC2_IMM) {
  301             if (is_carry) {
  302                 if (src2 >= 0)
  303                     FAIL_IF(push_inst(compiler, ORI | S(src1) | TA(EQUAL_FLAG) | IMM(src2), EQUAL_FLAG));
  304                 else {
  305                     FAIL_IF(push_inst(compiler, SELECT_OP(DADDIU, ADDIU) | SA(0) | TA(EQUAL_FLAG) | IMM(src2), EQUAL_FLAG));
  306                     FAIL_IF(push_inst(compiler, OR | S(src1) | TA(EQUAL_FLAG) | DA(EQUAL_FLAG), EQUAL_FLAG));
  307                 }
  308             }
  309             FAIL_IF(push_inst(compiler, SELECT_OP(DADDIU, ADDIU) | S(src1) | T(dst) | IMM(src2), DR(dst)));
  310         } else {
  311             if (is_carry)
  312                 FAIL_IF(push_inst(compiler, OR | S(src1) | T(src2) | DA(EQUAL_FLAG), EQUAL_FLAG));
  313             /* dst may be the same as src1 or src2. */
  314             FAIL_IF(push_inst(compiler, SELECT_OP(DADDU, ADDU) | S(src1) | T(src2) | D(dst), DR(dst)));
  315         }
  316         if (is_carry)
  317             FAIL_IF(push_inst(compiler, SLTU | S(dst) | TA(EQUAL_FLAG) | DA(EQUAL_FLAG), EQUAL_FLAG));
  318 
  319         FAIL_IF(push_inst(compiler, SELECT_OP(DADDU, ADDU) | S(dst) | TA(OTHER_FLAG) | D(dst), DR(dst)));
  320         if (!is_carry)
  321             return SLJIT_SUCCESS;
  322 
  323         /* Set ULESS_FLAG (dst == 0) && (OTHER_FLAG == 1). */
  324         FAIL_IF(push_inst(compiler, SLTU | S(dst) | TA(OTHER_FLAG) | DA(OTHER_FLAG), OTHER_FLAG));
  325         /* Set carry flag. */
  326         return push_inst(compiler, OR | SA(OTHER_FLAG) | TA(EQUAL_FLAG) | DA(OTHER_FLAG), OTHER_FLAG);
  327 
  328     case SLJIT_SUB:
  329         if ((flags & SRC2_IMM) && src2 == SIMM_MIN) {
  330             FAIL_IF(push_inst(compiler, ADDIU | SA(0) | T(TMP_REG2) | IMM(src2), DR(TMP_REG2)));
  331             src2 = TMP_REG2;
  332             flags &= ~SRC2_IMM;
  333         }
  334 
  335         is_handled = 0;
  336 
  337         if (flags & SRC2_IMM) {
  338             if (GET_FLAG_TYPE(op) == SLJIT_LESS || GET_FLAG_TYPE(op) == SLJIT_GREATER_EQUAL) {
  339                 FAIL_IF(push_inst(compiler, SLTIU | S(src1) | TA(OTHER_FLAG) | IMM(src2), OTHER_FLAG));
  340                 is_handled = 1;
  341             }
  342             else if (GET_FLAG_TYPE(op) == SLJIT_SIG_LESS || GET_FLAG_TYPE(op) == SLJIT_SIG_GREATER_EQUAL) {
  343                 FAIL_IF(push_inst(compiler, SLTI | S(src1) | TA(OTHER_FLAG) | IMM(src2), OTHER_FLAG));
  344                 is_handled = 1;
  345             }
  346         }
  347 
  348         if (!is_handled && GET_FLAG_TYPE(op) >= SLJIT_LESS && GET_FLAG_TYPE(op) <= SLJIT_SIG_LESS_EQUAL) {
  349             is_handled = 1;
  350 
  351             if (flags & SRC2_IMM) {
  352                 FAIL_IF(push_inst(compiler, ADDIU | SA(0) | T(TMP_REG2) | IMM(src2), DR(TMP_REG2)));
  353                 src2 = TMP_REG2;
  354                 flags &= ~SRC2_IMM;
  355             }
  356 
  357             if (GET_FLAG_TYPE(op) == SLJIT_LESS || GET_FLAG_TYPE(op) == SLJIT_GREATER_EQUAL) {
  358                 FAIL_IF(push_inst(compiler, SLTU | S(src1) | T(src2) | DA(OTHER_FLAG), OTHER_FLAG));
  359             }
  360             else if (GET_FLAG_TYPE(op) == SLJIT_GREATER || GET_FLAG_TYPE(op) == SLJIT_LESS_EQUAL)
  361             {
  362                 FAIL_IF(push_inst(compiler, SLTU | S(src2) | T(src1) | DA(OTHER_FLAG), OTHER_FLAG));
  363             }
  364             else if (GET_FLAG_TYPE(op) == SLJIT_SIG_LESS || GET_FLAG_TYPE(op) == SLJIT_SIG_GREATER_EQUAL) {
  365                 FAIL_IF(push_inst(compiler, SLT | S(src1) | T(src2) | DA(OTHER_FLAG), OTHER_FLAG));
  366             }
  367             else if (GET_FLAG_TYPE(op) == SLJIT_SIG_GREATER || GET_FLAG_TYPE(op) == SLJIT_SIG_LESS_EQUAL)
  368             {
  369                 FAIL_IF(push_inst(compiler, SLT | S(src2) | T(src1) | DA(OTHER_FLAG), OTHER_FLAG));
  370             }
  371         }
  372 
  373         if (is_handled) {
  374             if (flags & SRC2_IMM) {
  375                 if (op & SLJIT_SET_Z)
  376                     FAIL_IF(push_inst(compiler, SELECT_OP(DADDIU, ADDIU) | S(src1) | TA(EQUAL_FLAG) | IMM(-src2), EQUAL_FLAG));
  377                 if (!(flags & UNUSED_DEST))
  378                     return push_inst(compiler, SELECT_OP(DADDIU, ADDIU) | S(src1) | T(dst) | IMM(-src2), DR(dst));
  379             }
  380             else {
  381                 if (op & SLJIT_SET_Z)
  382                     FAIL_IF(push_inst(compiler, SELECT_OP(DSUBU, SUBU) | S(src1) | T(src2) | DA(EQUAL_FLAG), EQUAL_FLAG));
  383                 if (!(flags & UNUSED_DEST))
  384                     return push_inst(compiler, SELECT_OP(DSUBU, SUBU) | S(src1) | T(src2) | D(dst), DR(dst));
  385             }
  386             return SLJIT_SUCCESS;
  387         }
  388 
  389         is_overflow = GET_FLAG_TYPE(op) == SLJIT_OVERFLOW;
  390         is_carry = GET_FLAG_TYPE(op) == GET_FLAG_TYPE(SLJIT_SET_CARRY);
  391 
  392         if (flags & SRC2_IMM) {
  393             if (is_overflow) {
  394                 if (src2 >= 0)
  395                     FAIL_IF(push_inst(compiler, OR | S(src1) | T(src1) | DA(EQUAL_FLAG), EQUAL_FLAG));
  396                 else
  397                     FAIL_IF(push_inst(compiler, NOR | S(src1) | T(src1) | DA(EQUAL_FLAG), EQUAL_FLAG));
  398             }
  399             else if (op & SLJIT_SET_Z)
  400                 FAIL_IF(push_inst(compiler, SELECT_OP(DADDIU, ADDIU) | S(src1) | TA(EQUAL_FLAG) | IMM(-src2), EQUAL_FLAG));
  401 
  402             if (is_overflow || is_carry)
  403                 FAIL_IF(push_inst(compiler, SLTIU | S(src1) | TA(OTHER_FLAG) | IMM(src2), OTHER_FLAG));
  404             /* dst may be the same as src1 or src2. */
  405             if (!(flags & UNUSED_DEST) || (op & VARIABLE_FLAG_MASK))
  406                 FAIL_IF(push_inst(compiler, SELECT_OP(DADDIU, ADDIU) | S(src1) | T(dst) | IMM(-src2), DR(dst)));
  407         }
  408         else {
  409             if (is_overflow)
  410                 FAIL_IF(push_inst(compiler, XOR | S(src1) | T(src2) | DA(EQUAL_FLAG), EQUAL_FLAG));
  411             else if (op & SLJIT_SET_Z)
  412                 FAIL_IF(push_inst(compiler, SELECT_OP(DSUBU, SUBU) | S(src1) | T(src2) | DA(EQUAL_FLAG), EQUAL_FLAG));
  413 
  414             if (is_overflow || is_carry)
  415                 FAIL_IF(push_inst(compiler, SLTU | S(src1) | T(src2) | DA(OTHER_FLAG), OTHER_FLAG));
  416             /* dst may be the same as src1 or src2. */
  417             if (!(flags & UNUSED_DEST) || (op & VARIABLE_FLAG_MASK))
  418                 FAIL_IF(push_inst(compiler, SELECT_OP(DSUBU, SUBU) | S(src1) | T(src2) | D(dst), DR(dst)));
  419         }
  420 
  421         if (!is_overflow)
  422             return SLJIT_SUCCESS;
  423         FAIL_IF(push_inst(compiler, SELECT_OP(DSLL32, SLL) | TA(OTHER_FLAG) | D(TMP_REG1) | SH_IMM(31), DR(TMP_REG1)));
  424         FAIL_IF(push_inst(compiler, XOR | S(TMP_REG1) | TA(EQUAL_FLAG) | DA(EQUAL_FLAG), EQUAL_FLAG));
  425         FAIL_IF(push_inst(compiler, XOR | S(dst) | TA(EQUAL_FLAG) | DA(OTHER_FLAG), OTHER_FLAG));
  426         if (op & SLJIT_SET_Z)
  427             FAIL_IF(push_inst(compiler, SELECT_OP(DADDU, ADDU) | S(dst) | TA(0) | DA(EQUAL_FLAG), EQUAL_FLAG));
  428         return push_inst(compiler, SELECT_OP(DSRL32, SRL) | TA(OTHER_FLAG) | DA(OTHER_FLAG) | SH_IMM(31), OTHER_FLAG);
  429 
  430     case SLJIT_SUBC:
  431         if ((flags & SRC2_IMM) && src2 == SIMM_MIN) {
  432             FAIL_IF(push_inst(compiler, ADDIU | SA(0) | T(TMP_REG2) | IMM(src2), DR(TMP_REG2)));
  433             src2 = TMP_REG2;
  434             flags &= ~SRC2_IMM;
  435         }
  436 
  437         is_carry = GET_FLAG_TYPE(op) == GET_FLAG_TYPE(SLJIT_SET_CARRY);
  438 
  439         if (flags & SRC2_IMM) {
  440             if (is_carry)
  441                 FAIL_IF(push_inst(compiler, SLTIU | S(src1) | TA(EQUAL_FLAG) | IMM(src2), EQUAL_FLAG));
  442             /* dst may be the same as src1 or src2. */
  443             FAIL_IF(push_inst(compiler, SELECT_OP(DADDIU, ADDIU) | S(src1) | T(dst) | IMM(-src2), DR(dst)));
  444         }
  445         else {
  446             if (is_carry)
  447                 FAIL_IF(push_inst(compiler, SLTU | S(src1) | T(src2) | DA(EQUAL_FLAG), EQUAL_FLAG));
  448             /* dst may be the same as src1 or src2. */
  449             FAIL_IF(push_inst(compiler, SELECT_OP(DSUBU, SUBU) | S(src1) | T(src2) | D(dst), DR(dst)));
  450         }
  451 
  452         if (is_carry)
  453             FAIL_IF(push_inst(compiler, SLTU | S(dst) | TA(OTHER_FLAG) | D(TMP_REG1), DR(TMP_REG1)));
  454 
  455         FAIL_IF(push_inst(compiler, SELECT_OP(DSUBU, SUBU) | S(dst) | TA(OTHER_FLAG) | D(dst), DR(dst)));
  456         return (is_carry) ? push_inst(compiler, OR | SA(EQUAL_FLAG) | T(TMP_REG1) | DA(OTHER_FLAG), OTHER_FLAG) : SLJIT_SUCCESS;
  457 
  458     case SLJIT_MUL:
  459         SLJIT_ASSERT(!(flags & SRC2_IMM));
  460 
  461         if (GET_FLAG_TYPE(op) != SLJIT_MUL_OVERFLOW) {
  462 #if (defined SLJIT_MIPS_R1 && SLJIT_MIPS_R1)
  463             if (op & SLJIT_I32_OP)
  464                 return push_inst(compiler, MUL | S(src1) | T(src2) | D(dst), DR(dst));
  465             FAIL_IF(push_inst(compiler, DMULT | S(src1) | T(src2), MOVABLE_INS));
  466             return push_inst(compiler, MFLO | D(dst), DR(dst));
  467 #else
  468             FAIL_IF(push_inst(compiler, SELECT_OP(DMULT, MULT) | S(src1) | T(src2), MOVABLE_INS));
  469             return push_inst(compiler, MFLO | D(dst), DR(dst));
  470 #endif
  471         }
  472         FAIL_IF(push_inst(compiler, SELECT_OP(DMULT, MULT) | S(src1) | T(src2), MOVABLE_INS));
  473         FAIL_IF(push_inst(compiler, MFHI | DA(EQUAL_FLAG), EQUAL_FLAG));
  474         FAIL_IF(push_inst(compiler, MFLO | D(dst), DR(dst)));
  475         FAIL_IF(push_inst(compiler, SELECT_OP(DSRA32, SRA) | T(dst) | DA(OTHER_FLAG) | SH_IMM(31), OTHER_FLAG));
  476         return push_inst(compiler, SELECT_OP(DSUBU, SUBU) | SA(EQUAL_FLAG) | TA(OTHER_FLAG) | DA(OTHER_FLAG), OTHER_FLAG);
  477 
  478     case SLJIT_AND:
  479         EMIT_LOGICAL(ANDI, AND);
  480         return SLJIT_SUCCESS;
  481 
  482     case SLJIT_OR:
  483         EMIT_LOGICAL(ORI, OR);
  484         return SLJIT_SUCCESS;
  485 
  486     case SLJIT_XOR:
  487         EMIT_LOGICAL(XORI, XOR);
  488         return SLJIT_SUCCESS;
  489 
  490     case SLJIT_SHL:
  491         EMIT_SHIFT(DSLL, DSLL32, SLL, DSLLV, SLLV);
  492         return SLJIT_SUCCESS;
  493 
  494     case SLJIT_LSHR:
  495         EMIT_SHIFT(DSRL, DSRL32, SRL, DSRLV, SRLV);
  496         return SLJIT_SUCCESS;
  497 
  498     case SLJIT_ASHR:
  499         EMIT_SHIFT(DSRA, DSRA32, SRA, DSRAV, SRAV);
  500         return SLJIT_SUCCESS;
  501     }
  502 
  503     SLJIT_UNREACHABLE();
  504     return SLJIT_SUCCESS;
  505 }
  506 
  507 static SLJIT_INLINE sljit_s32 emit_const(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw init_value)
  508 {
  509     FAIL_IF(push_inst(compiler, LUI | T(dst) | IMM(init_value >> 48), DR(dst)));
  510     FAIL_IF(push_inst(compiler, ORI | S(dst) | T(dst) | IMM(init_value >> 32), DR(dst)));
  511     FAIL_IF(push_inst(compiler, DSLL | T(dst) | D(dst) | SH_IMM(16), DR(dst)));
  512     FAIL_IF(push_inst(compiler, ORI | S(dst) | T(dst) | IMM(init_value >> 16), DR(dst)));
  513     FAIL_IF(push_inst(compiler, DSLL | T(dst) | D(dst) | SH_IMM(16), DR(dst)));
  514     return push_inst(compiler, ORI | S(dst) | T(dst) | IMM(init_value), DR(dst));
  515 }
  516 
  517 SLJIT_API_FUNC_ATTRIBUTE void sljit_set_jump_addr(sljit_uw addr, sljit_uw new_target, sljit_sw executable_offset)
  518 {
  519     sljit_ins *inst = (sljit_ins *)addr;
  520 
  521     inst[0] = (inst[0] & 0xffff0000) | ((new_target >> 48) & 0xffff);
  522     inst[1] = (inst[1] & 0xffff0000) | ((new_target >> 32) & 0xffff);
  523     inst[3] = (inst[3] & 0xffff0000) | ((new_target >> 16) & 0xffff);
  524     inst[5] = (inst[5] & 0xffff0000) | (new_target & 0xffff);
  525     inst = (sljit_ins *)SLJIT_ADD_EXEC_OFFSET(inst, executable_offset);
  526     SLJIT_CACHE_FLUSH(inst, inst + 6);
  527 }
  528 
  529 SLJIT_API_FUNC_ATTRIBUTE void sljit_set_const(sljit_uw addr, sljit_sw new_constant, sljit_sw executable_offset)
  530 {
  531     sljit_ins *inst = (sljit_ins *)addr;
  532 
  533     inst[0] = (inst[0] & 0xffff0000) | ((new_constant >> 48) & 0xffff);
  534     inst[1] = (inst[1] & 0xffff0000) | ((new_constant >> 32) & 0xffff);
  535     inst[3] = (inst[3] & 0xffff0000) | ((new_constant >> 16) & 0xffff);
  536     inst[5] = (inst[5] & 0xffff0000) | (new_constant & 0xffff);
  537     inst = (sljit_ins *)SLJIT_ADD_EXEC_OFFSET(inst, executable_offset);
  538     SLJIT_CACHE_FLUSH(inst, inst + 6);
  539 }
  540 
  541 static sljit_s32 call_with_args(struct sljit_compiler *compiler, sljit_s32 arg_types, sljit_ins *ins_ptr)
  542 {
  543     sljit_s32 arg_count = 0;
  544     sljit_s32 word_arg_count = 0;
  545     sljit_s32 float_arg_count = 0;
  546     sljit_s32 types = 0;
  547     sljit_ins prev_ins = NOP;
  548     sljit_ins ins = NOP;
  549 
  550     SLJIT_ASSERT(reg_map[TMP_REG1] == 4 && freg_map[TMP_FREG1] == 12);
  551 
  552     arg_types >>= SLJIT_DEF_SHIFT;
  553 
  554     while (arg_types) {
  555         types = (types << SLJIT_DEF_SHIFT) | (arg_types & SLJIT_DEF_MASK);
  556 
  557         switch (arg_types & SLJIT_DEF_MASK) {
  558         case SLJIT_ARG_TYPE_F32:
  559         case SLJIT_ARG_TYPE_F64:
  560             arg_count++;
  561             float_arg_count++;
  562             break;
  563         default:
  564             arg_count++;
  565             word_arg_count++;
  566             break;
  567         }
  568 
  569         arg_types >>= SLJIT_DEF_SHIFT;
  570     }
  571 
  572     while (types) {
  573         switch (types & SLJIT_DEF_MASK) {
  574         case SLJIT_ARG_TYPE_F32:
  575             if (arg_count != float_arg_count)
  576                 ins = MOV_S | FMT_S | FS(float_arg_count) | FD(arg_count);
  577             else if (arg_count == 1)
  578                 ins = MOV_S | FMT_S | FS(SLJIT_FR0) | FD(TMP_FREG1);
  579             arg_count--;
  580             float_arg_count--;
  581             break;
  582         case SLJIT_ARG_TYPE_F64:
  583             if (arg_count != float_arg_count)
  584                 ins = MOV_S | FMT_D | FS(float_arg_count) | FD(arg_count);
  585             else if (arg_count == 1)
  586                 ins = MOV_S | FMT_D | FS(SLJIT_FR0) | FD(TMP_FREG1);
  587             arg_count--;
  588             float_arg_count--;
  589             break;
  590         default:
  591             if (arg_count != word_arg_count)
  592                 ins = DADDU | S(word_arg_count) | TA(0) | D(arg_count);
  593             else if (arg_count == 1)
  594                 ins = DADDU | S(SLJIT_R0) | TA(0) | DA(4);
  595             arg_count--;
  596             word_arg_count--;
  597             break;
  598         }
  599 
  600         if (ins != NOP) {
  601             if (prev_ins != NOP)
  602                 FAIL_IF(push_inst(compiler, prev_ins, MOVABLE_INS));
  603             prev_ins = ins;
  604             ins = NOP;
  605         }
  606 
  607         types >>= SLJIT_DEF_SHIFT;
  608     }
  609 
  610     *ins_ptr = prev_ins;
  611 
  612     return SLJIT_SUCCESS;
  613 }
  614 
  615 SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_call(struct sljit_compiler *compiler, sljit_s32 type,
  616     sljit_s32 arg_types)
  617 {
  618     struct sljit_jump *jump;
  619     sljit_ins ins;
  620 
  621     CHECK_ERROR_PTR();
  622     CHECK_PTR(check_sljit_emit_call(compiler, type, arg_types));
  623 
  624     jump = (struct sljit_jump*)ensure_abuf(compiler, sizeof(struct sljit_jump));
  625     PTR_FAIL_IF(!jump);
  626     set_jump(jump, compiler, type & SLJIT_REWRITABLE_JUMP);
  627     type &= 0xff;
  628 
  629     PTR_FAIL_IF(call_with_args(compiler, arg_types, &ins));
  630 
  631     SLJIT_ASSERT(DR(PIC_ADDR_REG) == 25 && PIC_ADDR_REG == TMP_REG2);
  632 
  633     PTR_FAIL_IF(emit_const(compiler, PIC_ADDR_REG, 0));
  634 
  635     jump->flags |= IS_JAL | IS_CALL;
  636     PTR_FAIL_IF(push_inst(compiler, JALR | S(PIC_ADDR_REG) | DA(RETURN_ADDR_REG), UNMOVABLE_INS));
  637     jump->addr = compiler->size;
  638     PTR_FAIL_IF(push_inst(compiler, ins, UNMOVABLE_INS));
  639 
  640     return jump;
  641 }
  642 
  643 SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_icall(struct sljit_compiler *compiler, sljit_s32 type,
  644     sljit_s32 arg_types,
  645     sljit_s32 src, sljit_sw srcw)
  646 {
  647     sljit_ins ins;
  648 
  649     CHECK_ERROR();
  650     CHECK(check_sljit_emit_icall(compiler, type, arg_types, src, srcw));
  651 
  652     SLJIT_ASSERT(DR(PIC_ADDR_REG) == 25 && PIC_ADDR_REG == TMP_REG2);
  653 
  654     if (src & SLJIT_IMM)
  655         FAIL_IF(load_immediate(compiler, DR(PIC_ADDR_REG), srcw));
  656     else if (FAST_IS_REG(src))
  657         FAIL_IF(push_inst(compiler, DADDU | S(src) | TA(0) | D(PIC_ADDR_REG), DR(PIC_ADDR_REG)));
  658     else if (src & SLJIT_MEM) {
  659         ADJUST_LOCAL_OFFSET(src, srcw);
  660         FAIL_IF(emit_op_mem(compiler, WORD_DATA | LOAD_DATA, DR(PIC_ADDR_REG), src, srcw));
  661     }
  662 
  663     FAIL_IF(call_with_args(compiler, arg_types, &ins));
  664 
  665     /* Register input. */
  666     FAIL_IF(push_inst(compiler, JALR | S(PIC_ADDR_REG) | DA(RETURN_ADDR_REG), UNMOVABLE_INS));
  667     return push_inst(compiler, ins, UNMOVABLE_INS);
  668 }