Annotation of embedaddon/pcre/sljit/sljitNativeMIPS_32.c, revision 1.1

1.1     ! misho       1: /*
        !             2:  *    Stack-less Just-In-Time compiler
        !             3:  *
        !             4:  *    Copyright 2009-2010 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 int load_immediate(struct sljit_compiler *compiler, int dst_ar, sljit_w 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_E) \
        !            44:                        FAIL_IF(push_inst(compiler, op_imm | S(src1) | TA(EQUAL_FLAG) | IMM(src2), EQUAL_FLAG)); \
        !            45:                if (CHECK_FLAGS(SLJIT_SET_E)) \
        !            46:                        FAIL_IF(push_inst(compiler, op_imm | S(src1) | T(dst) | IMM(src2), DR(dst))); \
        !            47:        } \
        !            48:        else { \
        !            49:                if (op & SLJIT_SET_E) \
        !            50:                        FAIL_IF(push_inst(compiler, op_norm | S(src1) | T(src2) | DA(EQUAL_FLAG), EQUAL_FLAG)); \
        !            51:                if (CHECK_FLAGS(SLJIT_SET_E)) \
        !            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_norm) \
        !            56:        if (flags & SRC2_IMM) { \
        !            57:                if (op & SLJIT_SET_E) \
        !            58:                        FAIL_IF(push_inst(compiler, op_imm | T(src1) | DA(EQUAL_FLAG) | SH_IMM(src2), EQUAL_FLAG)); \
        !            59:                if (CHECK_FLAGS(SLJIT_SET_E)) \
        !            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_E) \
        !            64:                        FAIL_IF(push_inst(compiler, op_norm | S(src2) | T(src1) | DA(EQUAL_FLAG), EQUAL_FLAG)); \
        !            65:                if (CHECK_FLAGS(SLJIT_SET_E)) \
        !            66:                        FAIL_IF(push_inst(compiler, op_norm | S(src2) | T(src1) | D(dst), DR(dst))); \
        !            67:        }
        !            68: 
        !            69: static SLJIT_INLINE int emit_single_op(struct sljit_compiler *compiler, int op, int flags,
        !            70:        int dst, int src1, sljit_w src2)
        !            71: {
        !            72:        int overflow_ra = 0;
        !            73: 
        !            74:        switch (GET_OPCODE(op)) {
        !            75:        case SLJIT_ADD:
        !            76:                if (flags & SRC2_IMM) {
        !            77:                        if (op & SLJIT_SET_O) {
        !            78:                                FAIL_IF(push_inst(compiler, SRL | T(src1) | DA(TMP_EREG1) | SH_IMM(31), TMP_EREG1));
        !            79:                                if (src2 < 0)
        !            80:                                        FAIL_IF(push_inst(compiler, XORI | SA(TMP_EREG1) | TA(TMP_EREG1) | IMM(1), TMP_EREG1));
        !            81:                        }
        !            82:                        if (op & SLJIT_SET_E)
        !            83:                                FAIL_IF(push_inst(compiler, ADDIU | S(src1) | TA(EQUAL_FLAG) | IMM(src2), EQUAL_FLAG));
        !            84:                        if (op & SLJIT_SET_C) {
        !            85:                                if (src2 >= 0)
        !            86:                                        FAIL_IF(push_inst(compiler, ORI | S(src1) | TA(ULESS_FLAG) | IMM(src2), ULESS_FLAG));
        !            87:                                else {
        !            88:                                        FAIL_IF(push_inst(compiler, ADDIU | SA(0) | TA(ULESS_FLAG) | IMM(src2), ULESS_FLAG));
        !            89:                                        FAIL_IF(push_inst(compiler, OR | S(src1) | TA(ULESS_FLAG) | DA(ULESS_FLAG), ULESS_FLAG));
        !            90:                                }
        !            91:                        }
        !            92:                        /* dst may be the same as src1 or src2. */
        !            93:                        if (CHECK_FLAGS(SLJIT_SET_E))
        !            94:                                FAIL_IF(push_inst(compiler, ADDIU | S(src1) | T(dst) | IMM(src2), DR(dst)));
        !            95:                        if (op & SLJIT_SET_O) {
        !            96:                                FAIL_IF(push_inst(compiler, SRL | T(dst) | DA(OVERFLOW_FLAG) | SH_IMM(31), OVERFLOW_FLAG));
        !            97:                                if (src2 < 0)
        !            98:                                        FAIL_IF(push_inst(compiler, XORI | SA(OVERFLOW_FLAG) | TA(OVERFLOW_FLAG) | IMM(1), OVERFLOW_FLAG));
        !            99:                        }
        !           100:                }
        !           101:                else {
        !           102:                        if (op & SLJIT_SET_O) {
        !           103:                                FAIL_IF(push_inst(compiler, XOR | S(src1) | T(src2) | DA(TMP_EREG1), TMP_EREG1));
        !           104:                                FAIL_IF(push_inst(compiler, SRL | TA(TMP_EREG1) | DA(TMP_EREG1) | SH_IMM(31), TMP_EREG1));
        !           105:                                if (src1 != dst)
        !           106:                                        overflow_ra = DR(src1);
        !           107:                                else if (src2 != dst)
        !           108:                                        overflow_ra = DR(src2);
        !           109:                                else {
        !           110:                                        /* Rare ocasion. */
        !           111:                                        FAIL_IF(push_inst(compiler, ADDU | S(src1) | TA(0) | DA(TMP_EREG2), TMP_EREG2));
        !           112:                                        overflow_ra = TMP_EREG2;
        !           113:                                }
        !           114:                        }
        !           115:                        if (op & SLJIT_SET_E)
        !           116:                                FAIL_IF(push_inst(compiler, ADDU | S(src1) | T(src2) | DA(EQUAL_FLAG), EQUAL_FLAG));
        !           117:                        if (op & SLJIT_SET_C)
        !           118:                                FAIL_IF(push_inst(compiler, OR | S(src1) | T(src2) | DA(ULESS_FLAG), ULESS_FLAG));
        !           119:                        /* dst may be the same as src1 or src2. */
        !           120:                        if (CHECK_FLAGS(SLJIT_SET_E))
        !           121:                                FAIL_IF(push_inst(compiler, ADDU | S(src1) | T(src2) | D(dst), DR(dst)));
        !           122:                        if (op & SLJIT_SET_O) {
        !           123:                                FAIL_IF(push_inst(compiler, XOR | S(dst) | TA(overflow_ra) | DA(OVERFLOW_FLAG), OVERFLOW_FLAG));
        !           124:                                FAIL_IF(push_inst(compiler, SRL | TA(OVERFLOW_FLAG) | DA(OVERFLOW_FLAG) | SH_IMM(31), OVERFLOW_FLAG));
        !           125:                        }
        !           126:                }
        !           127: 
        !           128:                /* a + b >= a | b (otherwise, the carry should be set to 1). */
        !           129:                if (op & SLJIT_SET_C)
        !           130:                        FAIL_IF(push_inst(compiler, SLTU | S(dst) | TA(ULESS_FLAG) | DA(ULESS_FLAG), ULESS_FLAG));
        !           131:                if (op & SLJIT_SET_O)
        !           132:                        return push_inst(compiler, MOVN | SA(0) | TA(TMP_EREG1) | DA(OVERFLOW_FLAG), OVERFLOW_FLAG);
        !           133:                return SLJIT_SUCCESS;
        !           134: 
        !           135:        case SLJIT_ADDC:
        !           136:                if (flags & SRC2_IMM) {
        !           137:                        if (op & SLJIT_SET_C) {
        !           138:                                if (src2 >= 0)
        !           139:                                        FAIL_IF(push_inst(compiler, ORI | S(src1) | TA(TMP_EREG1) | IMM(src2), TMP_EREG1));
        !           140:                                else {
        !           141:                                        FAIL_IF(push_inst(compiler, ADDIU | SA(0) | TA(TMP_EREG1) | IMM(src2), TMP_EREG1));
        !           142:                                        FAIL_IF(push_inst(compiler, OR | S(src1) | TA(TMP_EREG1) | DA(TMP_EREG1), TMP_EREG1));
        !           143:                                }
        !           144:                        }
        !           145:                        FAIL_IF(push_inst(compiler, ADDIU | S(src1) | T(dst) | IMM(src2), DR(dst)));
        !           146:                } else {
        !           147:                        if (op & SLJIT_SET_C)
        !           148:                                FAIL_IF(push_inst(compiler, OR | S(src1) | T(src2) | DA(TMP_EREG1), TMP_EREG1));
        !           149:                        /* dst may be the same as src1 or src2. */
        !           150:                        FAIL_IF(push_inst(compiler, ADDU | S(src1) | T(src2) | D(dst), DR(dst)));
        !           151:                }
        !           152:                if (op & SLJIT_SET_C)
        !           153:                        FAIL_IF(push_inst(compiler, SLTU | S(dst) | TA(TMP_EREG1) | DA(TMP_EREG1), TMP_EREG1));
        !           154: 
        !           155:                FAIL_IF(push_inst(compiler, ADDU | S(dst) | TA(ULESS_FLAG) | D(dst), DR(dst)));
        !           156:                if (!(op & SLJIT_SET_C))
        !           157:                        return SLJIT_SUCCESS;
        !           158: 
        !           159:                /* Set TMP_EREG2 (dst == 0) && (ULESS_FLAG == 1). */
        !           160:                FAIL_IF(push_inst(compiler, SLTIU | S(dst) | TA(TMP_EREG2) | IMM(1), TMP_EREG2));
        !           161:                FAIL_IF(push_inst(compiler, AND | SA(TMP_EREG2) | TA(ULESS_FLAG) | DA(TMP_EREG2), TMP_EREG2));
        !           162:                /* Set carry flag. */
        !           163:                return push_inst(compiler, OR | SA(TMP_EREG2) | TA(TMP_EREG1) | DA(ULESS_FLAG), ULESS_FLAG);
        !           164: 
        !           165:        case SLJIT_SUB:
        !           166:                if ((flags & SRC2_IMM) && ((op & (SLJIT_SET_S | SLJIT_SET_U)) || src2 == SIMM_MIN)) {
        !           167:                        FAIL_IF(push_inst(compiler, ADDIU | SA(0) | T(TMP_REG2) | IMM(src2), DR(TMP_REG2)));
        !           168:                        src2 = TMP_REG2;
        !           169:                        flags &= ~SRC2_IMM;
        !           170:                }
        !           171: 
        !           172:                if (flags & SRC2_IMM) {
        !           173:                        if (op & SLJIT_SET_O) {
        !           174:                                FAIL_IF(push_inst(compiler, SRL | T(src1) | DA(TMP_EREG1) | SH_IMM(31), TMP_EREG1));
        !           175:                                if (src2 < 0)
        !           176:                                        FAIL_IF(push_inst(compiler, XORI | SA(TMP_EREG1) | TA(TMP_EREG1) | IMM(1), TMP_EREG1));
        !           177:                                if (src1 != dst)
        !           178:                                        overflow_ra = DR(src1);
        !           179:                                else {
        !           180:                                        /* Rare ocasion. */
        !           181:                                        FAIL_IF(push_inst(compiler, ADDU | S(src1) | TA(0) | DA(TMP_EREG2), TMP_EREG2));
        !           182:                                        overflow_ra = TMP_EREG2;
        !           183:                                }
        !           184:                        }
        !           185:                        if (op & SLJIT_SET_E)
        !           186:                                FAIL_IF(push_inst(compiler, ADDIU | S(src1) | TA(EQUAL_FLAG) | IMM(-src2), EQUAL_FLAG));
        !           187:                        if (op & SLJIT_SET_C)
        !           188:                                FAIL_IF(push_inst(compiler, SLTIU | S(src1) | TA(ULESS_FLAG) | IMM(src2), ULESS_FLAG));
        !           189:                        /* dst may be the same as src1 or src2. */
        !           190:                        if (CHECK_FLAGS(SLJIT_SET_E))
        !           191:                                FAIL_IF(push_inst(compiler, ADDIU | S(src1) | T(dst) | IMM(-src2), DR(dst)));
        !           192:                }
        !           193:                else {
        !           194:                        if (op & SLJIT_SET_O) {
        !           195:                                FAIL_IF(push_inst(compiler, XOR | S(src1) | T(src2) | DA(TMP_EREG1), TMP_EREG1));
        !           196:                                FAIL_IF(push_inst(compiler, SRL | TA(TMP_EREG1) | DA(TMP_EREG1) | SH_IMM(31), TMP_EREG1));
        !           197:                                if (src1 != dst)
        !           198:                                        overflow_ra = DR(src1);
        !           199:                                else {
        !           200:                                        /* Rare ocasion. */
        !           201:                                        FAIL_IF(push_inst(compiler, ADDU | S(src1) | TA(0) | DA(TMP_EREG2), TMP_EREG2));
        !           202:                                        overflow_ra = TMP_EREG2;
        !           203:                                }
        !           204:                        }
        !           205:                        if (op & SLJIT_SET_E)
        !           206:                                FAIL_IF(push_inst(compiler, SUBU | S(src1) | T(src2) | DA(EQUAL_FLAG), EQUAL_FLAG));
        !           207:                        if (op & (SLJIT_SET_U | SLJIT_SET_C))
        !           208:                                FAIL_IF(push_inst(compiler, SLTU | S(src1) | T(src2) | DA(ULESS_FLAG), ULESS_FLAG));
        !           209:                        if (op & SLJIT_SET_U)
        !           210:                                FAIL_IF(push_inst(compiler, SLTU | S(src2) | T(src1) | DA(UGREATER_FLAG), UGREATER_FLAG));
        !           211:                        if (op & SLJIT_SET_S) {
        !           212:                                FAIL_IF(push_inst(compiler, SLT | S(src1) | T(src2) | DA(LESS_FLAG), LESS_FLAG));
        !           213:                                FAIL_IF(push_inst(compiler, SLT | S(src2) | T(src1) | DA(GREATER_FLAG), GREATER_FLAG));
        !           214:                        }
        !           215:                        /* dst may be the same as src1 or src2. */
        !           216:                        if (CHECK_FLAGS(SLJIT_SET_E | SLJIT_SET_S | SLJIT_SET_U | SLJIT_SET_C))
        !           217:                                FAIL_IF(push_inst(compiler, SUBU | S(src1) | T(src2) | D(dst), DR(dst)));
        !           218:                }
        !           219: 
        !           220:                if (op & SLJIT_SET_O) {
        !           221:                        FAIL_IF(push_inst(compiler, XOR | S(dst) | TA(overflow_ra) | DA(OVERFLOW_FLAG), OVERFLOW_FLAG));
        !           222:                        FAIL_IF(push_inst(compiler, SRL | TA(OVERFLOW_FLAG) | DA(OVERFLOW_FLAG) | SH_IMM(31), OVERFLOW_FLAG));
        !           223:                        return push_inst(compiler, MOVZ | SA(0) | TA(TMP_EREG1) | DA(OVERFLOW_FLAG), OVERFLOW_FLAG);
        !           224:                }
        !           225:                return SLJIT_SUCCESS;
        !           226: 
        !           227:        case SLJIT_SUBC:
        !           228:                if ((flags & SRC2_IMM) && src2 == SIMM_MIN) {
        !           229:                        FAIL_IF(push_inst(compiler, ADDIU | SA(0) | T(TMP_REG2) | IMM(src2), DR(TMP_REG2)));
        !           230:                        src2 = TMP_REG2;
        !           231:                        flags &= ~SRC2_IMM;
        !           232:                }
        !           233: 
        !           234:                if (flags & SRC2_IMM) {
        !           235:                        if (op & SLJIT_SET_C)
        !           236:                                FAIL_IF(push_inst(compiler, SLTIU | S(src1) | TA(TMP_EREG1) | IMM(-src2), TMP_EREG1));
        !           237:                        /* dst may be the same as src1 or src2. */
        !           238:                        FAIL_IF(push_inst(compiler, ADDIU | S(src1) | T(dst) | IMM(-src2), DR(dst)));
        !           239:                }
        !           240:                else {
        !           241:                        if (op & SLJIT_SET_C)
        !           242:                                FAIL_IF(push_inst(compiler, SLTU | S(src1) | T(src2) | DA(TMP_EREG1), TMP_EREG1));
        !           243:                        /* dst may be the same as src1 or src2. */
        !           244:                        FAIL_IF(push_inst(compiler, SUBU | S(src1) | T(src2) | D(dst), DR(dst)));
        !           245:                }
        !           246: 
        !           247:                if (op & SLJIT_SET_C)
        !           248:                        FAIL_IF(push_inst(compiler, MOVZ | SA(ULESS_FLAG) | T(dst) | DA(TMP_EREG1), TMP_EREG1));
        !           249: 
        !           250:                FAIL_IF(push_inst(compiler, SUBU | S(dst) | TA(ULESS_FLAG) | D(dst), DR(dst)));
        !           251: 
        !           252:                if (op & SLJIT_SET_C)
        !           253:                        FAIL_IF(push_inst(compiler, ADDU | SA(TMP_EREG1) | TA(0) | DA(ULESS_FLAG), ULESS_FLAG));
        !           254: 
        !           255:                return SLJIT_SUCCESS;
        !           256: 
        !           257:        case SLJIT_MUL:
        !           258:                SLJIT_ASSERT(!(flags & SRC2_IMM));
        !           259:                if (!(op & SLJIT_SET_O)) {
        !           260: #if (defined SLJIT_MIPS_32_64 && SLJIT_MIPS_32_64)
        !           261:                        return push_inst(compiler, MUL | S(src1) | T(src2) | D(dst), DR(dst));
        !           262: #else
        !           263:                        FAIL_IF(push_inst(compiler, MULT | S(src1) | T(src2), MOVABLE_INS));
        !           264:                        return push_inst(compiler, MFLO | D(dst), DR(dst));
        !           265: #endif
        !           266:                }
        !           267:                FAIL_IF(push_inst(compiler, MULT | S(src1) | T(src2), MOVABLE_INS));
        !           268:                FAIL_IF(push_inst(compiler, MFHI | DA(TMP_EREG1), TMP_EREG1));
        !           269:                FAIL_IF(push_inst(compiler, MFLO | D(dst), DR(dst)));
        !           270:                FAIL_IF(push_inst(compiler, SRA | T(dst) | DA(TMP_EREG2) | SH_IMM(31), TMP_EREG2));
        !           271:                return push_inst(compiler, SUBU | SA(TMP_EREG1) | TA(TMP_EREG2) | DA(OVERFLOW_FLAG), OVERFLOW_FLAG);
        !           272: 
        !           273:        case SLJIT_AND:
        !           274:                EMIT_LOGICAL(ANDI, AND);
        !           275:                return SLJIT_SUCCESS;
        !           276: 
        !           277:        case SLJIT_OR:
        !           278:                EMIT_LOGICAL(ORI, OR);
        !           279:                return SLJIT_SUCCESS;
        !           280: 
        !           281:        case SLJIT_XOR:
        !           282:                EMIT_LOGICAL(XORI, XOR);
        !           283:                return SLJIT_SUCCESS;
        !           284: 
        !           285:        case SLJIT_SHL:
        !           286:                EMIT_SHIFT(SLL, SLLV);
        !           287:                return SLJIT_SUCCESS;
        !           288: 
        !           289:        case SLJIT_LSHR:
        !           290:                EMIT_SHIFT(SRL, SRLV);
        !           291:                return SLJIT_SUCCESS;
        !           292: 
        !           293:        case SLJIT_ASHR:
        !           294:                EMIT_SHIFT(SRA, SRAV);
        !           295:                return SLJIT_SUCCESS;
        !           296: 
        !           297:        case SLJIT_MOV:
        !           298:        case SLJIT_MOV_UI:
        !           299:        case SLJIT_MOV_SI:
        !           300:                SLJIT_ASSERT(src1 == TMP_REG1);
        !           301:                if (dst != src2)
        !           302:                        return push_inst(compiler, ADDU | S(src2) | TA(0) | D(dst), DR(dst));
        !           303:                return SLJIT_SUCCESS;
        !           304: 
        !           305:        case SLJIT_MOV_UB:
        !           306:        case SLJIT_MOV_SB:
        !           307:                SLJIT_ASSERT(src1 == TMP_REG1);
        !           308:                if ((flags & (REG_DEST | REG2_SOURCE)) == (REG_DEST | REG2_SOURCE)) {
        !           309:                        if (op == SLJIT_MOV_SB) {
        !           310: #if (defined SLJIT_MIPS_32_64 && SLJIT_MIPS_32_64)
        !           311:                                return push_inst(compiler, SEB | T(src2) | D(dst), DR(dst));
        !           312: #else
        !           313:                                FAIL_IF(push_inst(compiler, SLL | T(src2) | D(dst) | SH_IMM(24), DR(dst)));
        !           314:                                return push_inst(compiler, SRA | T(dst) | D(dst) | SH_IMM(24), DR(dst));
        !           315: #endif
        !           316:                        }
        !           317:                        return push_inst(compiler, ANDI | S(src2) | T(dst) | IMM(0xff), DR(dst));
        !           318:                }
        !           319:                else if (dst != src2)
        !           320:                        SLJIT_ASSERT_STOP();
        !           321:                return SLJIT_SUCCESS;
        !           322: 
        !           323:        case SLJIT_MOV_UH:
        !           324:        case SLJIT_MOV_SH:
        !           325:                SLJIT_ASSERT(src1 == TMP_REG1);
        !           326:                if ((flags & (REG_DEST | REG2_SOURCE)) == (REG_DEST | REG2_SOURCE)) {
        !           327:                        if (op == SLJIT_MOV_SH) {
        !           328: #if (defined SLJIT_MIPS_32_64 && SLJIT_MIPS_32_64)
        !           329:                                return push_inst(compiler, SEH | T(src2) | D(dst), DR(dst));
        !           330: #else
        !           331:                                FAIL_IF(push_inst(compiler, SLL | T(src2) | D(dst) | SH_IMM(16), DR(dst)));
        !           332:                                return push_inst(compiler, SRA | T(dst) | D(dst) | SH_IMM(16), DR(dst));
        !           333: #endif
        !           334:                        }
        !           335:                        return push_inst(compiler, ANDI | S(src2) | T(dst) | IMM(0xffff), DR(dst));
        !           336:                }
        !           337:                else if (dst != src2)
        !           338:                        SLJIT_ASSERT_STOP();
        !           339:                return SLJIT_SUCCESS;
        !           340: 
        !           341:        case SLJIT_NOT:
        !           342:                SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & SRC2_IMM));
        !           343:                if (op & SLJIT_SET_E)
        !           344:                        FAIL_IF(push_inst(compiler, NOR | S(src2) | T(src2) | DA(EQUAL_FLAG), EQUAL_FLAG));
        !           345:                if (CHECK_FLAGS(SLJIT_SET_E))
        !           346:                        FAIL_IF(push_inst(compiler, NOR | S(src2) | T(src2) | D(dst), DR(dst)));
        !           347:                return SLJIT_SUCCESS;
        !           348: 
        !           349:        case SLJIT_CLZ:
        !           350:                SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & SRC2_IMM));
        !           351: #if (defined SLJIT_MIPS_32_64 && SLJIT_MIPS_32_64)
        !           352:                if (op & SLJIT_SET_E)
        !           353:                        FAIL_IF(push_inst(compiler, CLZ | S(src2) | TA(EQUAL_FLAG) | DA(EQUAL_FLAG), EQUAL_FLAG));
        !           354:                if (CHECK_FLAGS(SLJIT_SET_E))
        !           355:                        FAIL_IF(push_inst(compiler, CLZ | S(src2) | T(dst) | D(dst), DR(dst)));
        !           356: #else
        !           357:                if (SLJIT_UNLIKELY(flags & UNUSED_DEST)) {
        !           358:                        FAIL_IF(push_inst(compiler, SRL | T(src2) | DA(EQUAL_FLAG) | SH_IMM(31), EQUAL_FLAG));
        !           359:                        return push_inst(compiler, XORI | SA(EQUAL_FLAG) | TA(EQUAL_FLAG) | IMM(1), EQUAL_FLAG);
        !           360:                }
        !           361:                /* Nearly all instructions are unmovable in the following sequence. */
        !           362:                FAIL_IF(push_inst(compiler, ADDU_W | S(src2) | TA(0) | D(TMP_REG1), DR(TMP_REG1)));
        !           363:                /* Check zero. */
        !           364:                FAIL_IF(push_inst(compiler, BEQ | S(TMP_REG1) | TA(0) | IMM(6), UNMOVABLE_INS));
        !           365:                FAIL_IF(push_inst(compiler, ORI | SA(0) | T(dst) | IMM(32), UNMOVABLE_INS));
        !           366:                /* Check sign bit. */
        !           367:                FAIL_IF(push_inst(compiler, BLTZ | S(TMP_REG1) | IMM(4), UNMOVABLE_INS));
        !           368:                FAIL_IF(push_inst(compiler, ORI | SA(0) | T(dst) | IMM(0), UNMOVABLE_INS));
        !           369:                /* Loop for searching the highest bit. */
        !           370:                FAIL_IF(push_inst(compiler, SLL | T(TMP_REG1) | D(TMP_REG1) | SH_IMM(1), DR(TMP_REG1)));
        !           371:                FAIL_IF(push_inst(compiler, BGEZ | S(TMP_REG1) | IMM(-2), UNMOVABLE_INS));
        !           372:                FAIL_IF(push_inst(compiler, ADDIU_W | S(dst) | T(dst) | IMM(1), UNMOVABLE_INS));
        !           373:                if (op & SLJIT_SET_E)
        !           374:                        return push_inst(compiler, ADDU_W | S(dst) | TA(0) | DA(EQUAL_FLAG), EQUAL_FLAG);
        !           375: #endif
        !           376:                return SLJIT_SUCCESS;
        !           377:        }
        !           378: 
        !           379:        SLJIT_ASSERT_STOP();
        !           380:        return SLJIT_SUCCESS;
        !           381: }
        !           382: 
        !           383: static SLJIT_INLINE int emit_const(struct sljit_compiler *compiler, int reg, sljit_w init_value)
        !           384: {
        !           385:        FAIL_IF(push_inst(compiler, LUI | T(reg) | IMM(init_value >> 16), DR(reg)));
        !           386:        return push_inst(compiler, ORI | S(reg) | T(reg) | IMM(init_value), DR(reg));
        !           387: }
        !           388: 
        !           389: SLJIT_API_FUNC_ATTRIBUTE void sljit_set_jump_addr(sljit_uw addr, sljit_uw new_addr)
        !           390: {
        !           391:        sljit_ins *inst = (sljit_ins*)addr;
        !           392: 
        !           393:        inst[0] = (inst[0] & 0xffff0000) | ((new_addr >> 16) & 0xffff);
        !           394:        inst[1] = (inst[1] & 0xffff0000) | (new_addr & 0xffff);
        !           395:        SLJIT_CACHE_FLUSH(inst, inst + 2);
        !           396: }
        !           397: 
        !           398: SLJIT_API_FUNC_ATTRIBUTE void sljit_set_const(sljit_uw addr, sljit_w new_constant)
        !           399: {
        !           400:        sljit_ins *inst = (sljit_ins*)addr;
        !           401: 
        !           402:        inst[0] = (inst[0] & 0xffff0000) | ((new_constant >> 16) & 0xffff);
        !           403:        inst[1] = (inst[1] & 0xffff0000) | (new_constant & 0xffff);
        !           404:        SLJIT_CACHE_FLUSH(inst, inst + 2);
        !           405: }

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>