1 1.4 alnsn /* $NetBSD: sljitNativeMIPS_32.c,v 1.4 2019/01/20 23:14:16 alnsn Exp $ */ 2 1.2 alnsn 3 1.1 alnsn /* 4 1.1 alnsn * Stack-less Just-In-Time compiler 5 1.1 alnsn * 6 1.4 alnsn * Copyright Zoltan Herczeg (hzmester (at) freemail.hu). All rights reserved. 7 1.1 alnsn * 8 1.1 alnsn * Redistribution and use in source and binary forms, with or without modification, are 9 1.1 alnsn * permitted provided that the following conditions are met: 10 1.1 alnsn * 11 1.1 alnsn * 1. Redistributions of source code must retain the above copyright notice, this list of 12 1.1 alnsn * conditions and the following disclaimer. 13 1.1 alnsn * 14 1.1 alnsn * 2. Redistributions in binary form must reproduce the above copyright notice, this list 15 1.1 alnsn * of conditions and the following disclaimer in the documentation and/or other materials 16 1.1 alnsn * provided with the distribution. 17 1.1 alnsn * 18 1.1 alnsn * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) AND CONTRIBUTORS ``AS IS'' AND ANY 19 1.1 alnsn * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 20 1.1 alnsn * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT 21 1.1 alnsn * SHALL THE COPYRIGHT HOLDER(S) OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 22 1.1 alnsn * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED 23 1.1 alnsn * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR 24 1.1 alnsn * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 25 1.1 alnsn * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 26 1.1 alnsn * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 1.1 alnsn */ 28 1.1 alnsn 29 1.1 alnsn /* mips 32-bit arch dependent functions. */ 30 1.1 alnsn 31 1.3 alnsn static sljit_s32 load_immediate(struct sljit_compiler *compiler, sljit_s32 dst_ar, sljit_sw imm) 32 1.1 alnsn { 33 1.1 alnsn if (!(imm & ~0xffff)) 34 1.1 alnsn return push_inst(compiler, ORI | SA(0) | TA(dst_ar) | IMM(imm), dst_ar); 35 1.1 alnsn 36 1.1 alnsn if (imm < 0 && imm >= SIMM_MIN) 37 1.1 alnsn return push_inst(compiler, ADDIU | SA(0) | TA(dst_ar) | IMM(imm), dst_ar); 38 1.1 alnsn 39 1.1 alnsn FAIL_IF(push_inst(compiler, LUI | TA(dst_ar) | IMM(imm >> 16), dst_ar)); 40 1.1 alnsn return (imm & 0xffff) ? push_inst(compiler, ORI | SA(dst_ar) | TA(dst_ar) | IMM(imm), dst_ar) : SLJIT_SUCCESS; 41 1.1 alnsn } 42 1.1 alnsn 43 1.1 alnsn #define EMIT_LOGICAL(op_imm, op_norm) \ 44 1.1 alnsn if (flags & SRC2_IMM) { \ 45 1.4 alnsn if (op & SLJIT_SET_Z) \ 46 1.1 alnsn FAIL_IF(push_inst(compiler, op_imm | S(src1) | TA(EQUAL_FLAG) | IMM(src2), EQUAL_FLAG)); \ 47 1.4 alnsn if (!(flags & UNUSED_DEST)) \ 48 1.1 alnsn FAIL_IF(push_inst(compiler, op_imm | S(src1) | T(dst) | IMM(src2), DR(dst))); \ 49 1.1 alnsn } \ 50 1.1 alnsn else { \ 51 1.4 alnsn if (op & SLJIT_SET_Z) \ 52 1.1 alnsn FAIL_IF(push_inst(compiler, op_norm | S(src1) | T(src2) | DA(EQUAL_FLAG), EQUAL_FLAG)); \ 53 1.4 alnsn if (!(flags & UNUSED_DEST)) \ 54 1.1 alnsn FAIL_IF(push_inst(compiler, op_norm | S(src1) | T(src2) | D(dst), DR(dst))); \ 55 1.1 alnsn } 56 1.1 alnsn 57 1.2 alnsn #define EMIT_SHIFT(op_imm, op_v) \ 58 1.1 alnsn if (flags & SRC2_IMM) { \ 59 1.4 alnsn if (op & SLJIT_SET_Z) \ 60 1.1 alnsn FAIL_IF(push_inst(compiler, op_imm | T(src1) | DA(EQUAL_FLAG) | SH_IMM(src2), EQUAL_FLAG)); \ 61 1.4 alnsn if (!(flags & UNUSED_DEST)) \ 62 1.1 alnsn FAIL_IF(push_inst(compiler, op_imm | T(src1) | D(dst) | SH_IMM(src2), DR(dst))); \ 63 1.1 alnsn } \ 64 1.1 alnsn else { \ 65 1.4 alnsn if (op & SLJIT_SET_Z) \ 66 1.2 alnsn FAIL_IF(push_inst(compiler, op_v | S(src2) | T(src1) | DA(EQUAL_FLAG), EQUAL_FLAG)); \ 67 1.4 alnsn if (!(flags & UNUSED_DEST)) \ 68 1.2 alnsn FAIL_IF(push_inst(compiler, op_v | S(src2) | T(src1) | D(dst), DR(dst))); \ 69 1.1 alnsn } 70 1.1 alnsn 71 1.3 alnsn static SLJIT_INLINE sljit_s32 emit_single_op(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 flags, 72 1.3 alnsn sljit_s32 dst, sljit_s32 src1, sljit_sw src2) 73 1.1 alnsn { 74 1.4 alnsn sljit_s32 is_overflow, is_carry, is_handled; 75 1.4 alnsn 76 1.2 alnsn switch (GET_OPCODE(op)) { 77 1.2 alnsn case SLJIT_MOV: 78 1.3 alnsn case SLJIT_MOV_U32: 79 1.3 alnsn case SLJIT_MOV_S32: 80 1.2 alnsn case SLJIT_MOV_P: 81 1.2 alnsn SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & SRC2_IMM)); 82 1.2 alnsn if (dst != src2) 83 1.2 alnsn return push_inst(compiler, ADDU | S(src2) | TA(0) | D(dst), DR(dst)); 84 1.2 alnsn return SLJIT_SUCCESS; 85 1.2 alnsn 86 1.3 alnsn case SLJIT_MOV_U8: 87 1.3 alnsn case SLJIT_MOV_S8: 88 1.2 alnsn SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & SRC2_IMM)); 89 1.2 alnsn if ((flags & (REG_DEST | REG2_SOURCE)) == (REG_DEST | REG2_SOURCE)) { 90 1.3 alnsn if (op == SLJIT_MOV_S8) { 91 1.3 alnsn #if (defined SLJIT_MIPS_R1 && SLJIT_MIPS_R1) 92 1.2 alnsn return push_inst(compiler, SEB | T(src2) | D(dst), DR(dst)); 93 1.2 alnsn #else 94 1.2 alnsn FAIL_IF(push_inst(compiler, SLL | T(src2) | D(dst) | SH_IMM(24), DR(dst))); 95 1.2 alnsn return push_inst(compiler, SRA | T(dst) | D(dst) | SH_IMM(24), DR(dst)); 96 1.2 alnsn #endif 97 1.2 alnsn } 98 1.2 alnsn return push_inst(compiler, ANDI | S(src2) | T(dst) | IMM(0xff), DR(dst)); 99 1.2 alnsn } 100 1.4 alnsn else { 101 1.4 alnsn SLJIT_ASSERT(dst == src2); 102 1.4 alnsn } 103 1.2 alnsn return SLJIT_SUCCESS; 104 1.2 alnsn 105 1.3 alnsn case SLJIT_MOV_U16: 106 1.3 alnsn case SLJIT_MOV_S16: 107 1.2 alnsn SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & SRC2_IMM)); 108 1.2 alnsn if ((flags & (REG_DEST | REG2_SOURCE)) == (REG_DEST | REG2_SOURCE)) { 109 1.3 alnsn if (op == SLJIT_MOV_S16) { 110 1.3 alnsn #if (defined SLJIT_MIPS_R1 && SLJIT_MIPS_R1) 111 1.2 alnsn return push_inst(compiler, SEH | T(src2) | D(dst), DR(dst)); 112 1.2 alnsn #else 113 1.2 alnsn FAIL_IF(push_inst(compiler, SLL | T(src2) | D(dst) | SH_IMM(16), DR(dst))); 114 1.2 alnsn return push_inst(compiler, SRA | T(dst) | D(dst) | SH_IMM(16), DR(dst)); 115 1.2 alnsn #endif 116 1.2 alnsn } 117 1.2 alnsn return push_inst(compiler, ANDI | S(src2) | T(dst) | IMM(0xffff), DR(dst)); 118 1.2 alnsn } 119 1.4 alnsn else { 120 1.4 alnsn SLJIT_ASSERT(dst == src2); 121 1.4 alnsn } 122 1.2 alnsn return SLJIT_SUCCESS; 123 1.2 alnsn 124 1.2 alnsn case SLJIT_NOT: 125 1.2 alnsn SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & SRC2_IMM)); 126 1.4 alnsn if (op & SLJIT_SET_Z) 127 1.2 alnsn FAIL_IF(push_inst(compiler, NOR | S(src2) | T(src2) | DA(EQUAL_FLAG), EQUAL_FLAG)); 128 1.4 alnsn if (!(flags & UNUSED_DEST)) 129 1.2 alnsn FAIL_IF(push_inst(compiler, NOR | S(src2) | T(src2) | D(dst), DR(dst))); 130 1.2 alnsn return SLJIT_SUCCESS; 131 1.2 alnsn 132 1.2 alnsn case SLJIT_CLZ: 133 1.2 alnsn SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & SRC2_IMM)); 134 1.3 alnsn #if (defined SLJIT_MIPS_R1 && SLJIT_MIPS_R1) 135 1.4 alnsn if (op & SLJIT_SET_Z) 136 1.2 alnsn FAIL_IF(push_inst(compiler, CLZ | S(src2) | TA(EQUAL_FLAG) | DA(EQUAL_FLAG), EQUAL_FLAG)); 137 1.4 alnsn if (!(flags & UNUSED_DEST)) 138 1.2 alnsn FAIL_IF(push_inst(compiler, CLZ | S(src2) | T(dst) | D(dst), DR(dst))); 139 1.2 alnsn #else 140 1.2 alnsn if (SLJIT_UNLIKELY(flags & UNUSED_DEST)) { 141 1.2 alnsn FAIL_IF(push_inst(compiler, SRL | T(src2) | DA(EQUAL_FLAG) | SH_IMM(31), EQUAL_FLAG)); 142 1.2 alnsn return push_inst(compiler, XORI | SA(EQUAL_FLAG) | TA(EQUAL_FLAG) | IMM(1), EQUAL_FLAG); 143 1.2 alnsn } 144 1.2 alnsn /* Nearly all instructions are unmovable in the following sequence. */ 145 1.2 alnsn FAIL_IF(push_inst(compiler, ADDU | S(src2) | TA(0) | D(TMP_REG1), DR(TMP_REG1))); 146 1.2 alnsn /* Check zero. */ 147 1.2 alnsn FAIL_IF(push_inst(compiler, BEQ | S(TMP_REG1) | TA(0) | IMM(5), UNMOVABLE_INS)); 148 1.2 alnsn FAIL_IF(push_inst(compiler, ORI | SA(0) | T(dst) | IMM(32), UNMOVABLE_INS)); 149 1.2 alnsn FAIL_IF(push_inst(compiler, ADDIU | SA(0) | T(dst) | IMM(-1), DR(dst))); 150 1.2 alnsn /* Loop for searching the highest bit. */ 151 1.2 alnsn FAIL_IF(push_inst(compiler, ADDIU | S(dst) | T(dst) | IMM(1), DR(dst))); 152 1.2 alnsn FAIL_IF(push_inst(compiler, BGEZ | S(TMP_REG1) | IMM(-2), UNMOVABLE_INS)); 153 1.2 alnsn FAIL_IF(push_inst(compiler, SLL | T(TMP_REG1) | D(TMP_REG1) | SH_IMM(1), UNMOVABLE_INS)); 154 1.4 alnsn if (op & SLJIT_SET_Z) 155 1.2 alnsn return push_inst(compiler, ADDU | S(dst) | TA(0) | DA(EQUAL_FLAG), EQUAL_FLAG); 156 1.2 alnsn #endif 157 1.2 alnsn return SLJIT_SUCCESS; 158 1.1 alnsn 159 1.1 alnsn case SLJIT_ADD: 160 1.4 alnsn is_overflow = GET_FLAG_TYPE(op) == SLJIT_OVERFLOW || GET_FLAG_TYPE(op) == SLJIT_NOT_OVERFLOW; 161 1.4 alnsn is_carry = GET_FLAG_TYPE(op) == GET_FLAG_TYPE(SLJIT_SET_CARRY); 162 1.4 alnsn 163 1.1 alnsn if (flags & SRC2_IMM) { 164 1.4 alnsn if (is_overflow) { 165 1.2 alnsn if (src2 >= 0) 166 1.4 alnsn FAIL_IF(push_inst(compiler, OR | S(src1) | T(src1) | DA(EQUAL_FLAG), EQUAL_FLAG)); 167 1.2 alnsn else 168 1.4 alnsn FAIL_IF(push_inst(compiler, NOR | S(src1) | T(src1) | DA(EQUAL_FLAG), EQUAL_FLAG)); 169 1.1 alnsn } 170 1.4 alnsn else if (op & SLJIT_SET_Z) 171 1.1 alnsn FAIL_IF(push_inst(compiler, ADDIU | S(src1) | TA(EQUAL_FLAG) | IMM(src2), EQUAL_FLAG)); 172 1.4 alnsn 173 1.4 alnsn if (is_overflow || is_carry) { 174 1.1 alnsn if (src2 >= 0) 175 1.4 alnsn FAIL_IF(push_inst(compiler, ORI | S(src1) | TA(OTHER_FLAG) | IMM(src2), OTHER_FLAG)); 176 1.1 alnsn else { 177 1.4 alnsn FAIL_IF(push_inst(compiler, ADDIU | SA(0) | TA(OTHER_FLAG) | IMM(src2), OTHER_FLAG)); 178 1.4 alnsn FAIL_IF(push_inst(compiler, OR | S(src1) | TA(OTHER_FLAG) | DA(OTHER_FLAG), OTHER_FLAG)); 179 1.1 alnsn } 180 1.1 alnsn } 181 1.1 alnsn /* dst may be the same as src1 or src2. */ 182 1.4 alnsn if (!(flags & UNUSED_DEST) || (op & VARIABLE_FLAG_MASK)) 183 1.1 alnsn FAIL_IF(push_inst(compiler, ADDIU | S(src1) | T(dst) | IMM(src2), DR(dst))); 184 1.1 alnsn } 185 1.1 alnsn else { 186 1.4 alnsn if (is_overflow) 187 1.4 alnsn FAIL_IF(push_inst(compiler, XOR | S(src1) | T(src2) | DA(EQUAL_FLAG), EQUAL_FLAG)); 188 1.4 alnsn else if (op & SLJIT_SET_Z) 189 1.1 alnsn FAIL_IF(push_inst(compiler, ADDU | S(src1) | T(src2) | DA(EQUAL_FLAG), EQUAL_FLAG)); 190 1.4 alnsn 191 1.4 alnsn if (is_overflow || is_carry) 192 1.4 alnsn FAIL_IF(push_inst(compiler, OR | S(src1) | T(src2) | DA(OTHER_FLAG), OTHER_FLAG)); 193 1.1 alnsn /* dst may be the same as src1 or src2. */ 194 1.4 alnsn if (!(flags & UNUSED_DEST) || (op & VARIABLE_FLAG_MASK)) 195 1.1 alnsn FAIL_IF(push_inst(compiler, ADDU | S(src1) | T(src2) | D(dst), DR(dst))); 196 1.1 alnsn } 197 1.1 alnsn 198 1.1 alnsn /* a + b >= a | b (otherwise, the carry should be set to 1). */ 199 1.4 alnsn if (is_overflow || is_carry) 200 1.4 alnsn FAIL_IF(push_inst(compiler, SLTU | S(dst) | TA(OTHER_FLAG) | DA(OTHER_FLAG), OTHER_FLAG)); 201 1.4 alnsn if (!is_overflow) 202 1.2 alnsn return SLJIT_SUCCESS; 203 1.4 alnsn FAIL_IF(push_inst(compiler, SLL | TA(OTHER_FLAG) | D(TMP_REG1) | SH_IMM(31), DR(TMP_REG1))); 204 1.4 alnsn FAIL_IF(push_inst(compiler, XOR | S(TMP_REG1) | TA(EQUAL_FLAG) | DA(EQUAL_FLAG), EQUAL_FLAG)); 205 1.4 alnsn FAIL_IF(push_inst(compiler, XOR | S(dst) | TA(EQUAL_FLAG) | DA(OTHER_FLAG), OTHER_FLAG)); 206 1.4 alnsn if (op & SLJIT_SET_Z) 207 1.4 alnsn FAIL_IF(push_inst(compiler, ADDU | S(dst) | TA(0) | DA(EQUAL_FLAG), EQUAL_FLAG)); 208 1.4 alnsn return push_inst(compiler, SRL | TA(OTHER_FLAG) | DA(OTHER_FLAG) | SH_IMM(31), OTHER_FLAG); 209 1.1 alnsn 210 1.1 alnsn case SLJIT_ADDC: 211 1.4 alnsn is_carry = GET_FLAG_TYPE(op) == GET_FLAG_TYPE(SLJIT_SET_CARRY); 212 1.4 alnsn 213 1.1 alnsn if (flags & SRC2_IMM) { 214 1.4 alnsn if (is_carry) { 215 1.1 alnsn if (src2 >= 0) 216 1.4 alnsn FAIL_IF(push_inst(compiler, ORI | S(src1) | TA(EQUAL_FLAG) | IMM(src2), EQUAL_FLAG)); 217 1.1 alnsn else { 218 1.4 alnsn FAIL_IF(push_inst(compiler, ADDIU | SA(0) | TA(EQUAL_FLAG) | IMM(src2), EQUAL_FLAG)); 219 1.4 alnsn FAIL_IF(push_inst(compiler, OR | S(src1) | TA(EQUAL_FLAG) | DA(EQUAL_FLAG), EQUAL_FLAG)); 220 1.1 alnsn } 221 1.1 alnsn } 222 1.1 alnsn FAIL_IF(push_inst(compiler, ADDIU | S(src1) | T(dst) | IMM(src2), DR(dst))); 223 1.1 alnsn } else { 224 1.4 alnsn if (is_carry) 225 1.4 alnsn FAIL_IF(push_inst(compiler, OR | S(src1) | T(src2) | DA(EQUAL_FLAG), EQUAL_FLAG)); 226 1.1 alnsn /* dst may be the same as src1 or src2. */ 227 1.1 alnsn FAIL_IF(push_inst(compiler, ADDU | S(src1) | T(src2) | D(dst), DR(dst))); 228 1.1 alnsn } 229 1.4 alnsn if (is_carry) 230 1.4 alnsn FAIL_IF(push_inst(compiler, SLTU | S(dst) | TA(EQUAL_FLAG) | DA(EQUAL_FLAG), EQUAL_FLAG)); 231 1.1 alnsn 232 1.4 alnsn FAIL_IF(push_inst(compiler, ADDU | S(dst) | TA(OTHER_FLAG) | D(dst), DR(dst))); 233 1.4 alnsn if (!is_carry) 234 1.1 alnsn return SLJIT_SUCCESS; 235 1.1 alnsn 236 1.4 alnsn /* Set ULESS_FLAG (dst == 0) && (OTHER_FLAG == 1). */ 237 1.4 alnsn FAIL_IF(push_inst(compiler, SLTU | S(dst) | TA(OTHER_FLAG) | DA(OTHER_FLAG), OTHER_FLAG)); 238 1.1 alnsn /* Set carry flag. */ 239 1.4 alnsn return push_inst(compiler, OR | SA(OTHER_FLAG) | TA(EQUAL_FLAG) | DA(OTHER_FLAG), OTHER_FLAG); 240 1.1 alnsn 241 1.1 alnsn case SLJIT_SUB: 242 1.4 alnsn if ((flags & SRC2_IMM) && src2 == SIMM_MIN) { 243 1.1 alnsn FAIL_IF(push_inst(compiler, ADDIU | SA(0) | T(TMP_REG2) | IMM(src2), DR(TMP_REG2))); 244 1.1 alnsn src2 = TMP_REG2; 245 1.1 alnsn flags &= ~SRC2_IMM; 246 1.1 alnsn } 247 1.1 alnsn 248 1.4 alnsn is_handled = 0; 249 1.4 alnsn 250 1.4 alnsn if (flags & SRC2_IMM) { 251 1.4 alnsn if (GET_FLAG_TYPE(op) == SLJIT_LESS || GET_FLAG_TYPE(op) == SLJIT_GREATER_EQUAL) { 252 1.4 alnsn FAIL_IF(push_inst(compiler, SLTIU | S(src1) | TA(OTHER_FLAG) | IMM(src2), OTHER_FLAG)); 253 1.4 alnsn is_handled = 1; 254 1.4 alnsn } 255 1.4 alnsn else if (GET_FLAG_TYPE(op) == SLJIT_SIG_LESS || GET_FLAG_TYPE(op) == SLJIT_SIG_GREATER_EQUAL) { 256 1.4 alnsn FAIL_IF(push_inst(compiler, SLTI | S(src1) | TA(OTHER_FLAG) | IMM(src2), OTHER_FLAG)); 257 1.4 alnsn is_handled = 1; 258 1.4 alnsn } 259 1.4 alnsn } 260 1.4 alnsn 261 1.4 alnsn if (!is_handled && GET_FLAG_TYPE(op) >= SLJIT_LESS && GET_FLAG_TYPE(op) <= SLJIT_SIG_LESS_EQUAL) { 262 1.4 alnsn is_handled = 1; 263 1.4 alnsn 264 1.4 alnsn if (flags & SRC2_IMM) { 265 1.4 alnsn FAIL_IF(push_inst(compiler, ADDIU | SA(0) | T(TMP_REG2) | IMM(src2), DR(TMP_REG2))); 266 1.4 alnsn src2 = TMP_REG2; 267 1.4 alnsn flags &= ~SRC2_IMM; 268 1.4 alnsn } 269 1.4 alnsn 270 1.4 alnsn if (GET_FLAG_TYPE(op) == SLJIT_LESS || GET_FLAG_TYPE(op) == SLJIT_GREATER_EQUAL) { 271 1.4 alnsn FAIL_IF(push_inst(compiler, SLTU | S(src1) | T(src2) | DA(OTHER_FLAG), OTHER_FLAG)); 272 1.4 alnsn } 273 1.4 alnsn else if (GET_FLAG_TYPE(op) == SLJIT_GREATER || GET_FLAG_TYPE(op) == SLJIT_LESS_EQUAL) 274 1.4 alnsn { 275 1.4 alnsn FAIL_IF(push_inst(compiler, SLTU | S(src2) | T(src1) | DA(OTHER_FLAG), OTHER_FLAG)); 276 1.4 alnsn } 277 1.4 alnsn else if (GET_FLAG_TYPE(op) == SLJIT_SIG_LESS || GET_FLAG_TYPE(op) == SLJIT_SIG_GREATER_EQUAL) { 278 1.4 alnsn FAIL_IF(push_inst(compiler, SLT | S(src1) | T(src2) | DA(OTHER_FLAG), OTHER_FLAG)); 279 1.4 alnsn } 280 1.4 alnsn else if (GET_FLAG_TYPE(op) == SLJIT_SIG_GREATER || GET_FLAG_TYPE(op) == SLJIT_SIG_LESS_EQUAL) 281 1.4 alnsn { 282 1.4 alnsn FAIL_IF(push_inst(compiler, SLT | S(src2) | T(src1) | DA(OTHER_FLAG), OTHER_FLAG)); 283 1.4 alnsn } 284 1.4 alnsn } 285 1.4 alnsn 286 1.4 alnsn if (is_handled) { 287 1.4 alnsn if (flags & SRC2_IMM) { 288 1.4 alnsn if (op & SLJIT_SET_Z) 289 1.4 alnsn FAIL_IF(push_inst(compiler, ADDIU | S(src1) | TA(EQUAL_FLAG) | IMM(-src2), EQUAL_FLAG)); 290 1.4 alnsn if (!(flags & UNUSED_DEST)) 291 1.4 alnsn return push_inst(compiler, ADDIU | S(src1) | T(dst) | IMM(-src2), DR(dst)); 292 1.4 alnsn } 293 1.4 alnsn else { 294 1.4 alnsn if (op & SLJIT_SET_Z) 295 1.4 alnsn FAIL_IF(push_inst(compiler, SUBU | S(src1) | T(src2) | DA(EQUAL_FLAG), EQUAL_FLAG)); 296 1.4 alnsn if (!(flags & UNUSED_DEST)) 297 1.4 alnsn return push_inst(compiler, SUBU | S(src1) | T(src2) | D(dst), DR(dst)); 298 1.4 alnsn } 299 1.4 alnsn return SLJIT_SUCCESS; 300 1.4 alnsn } 301 1.4 alnsn 302 1.4 alnsn is_overflow = GET_FLAG_TYPE(op) == SLJIT_OVERFLOW || GET_FLAG_TYPE(op) == SLJIT_NOT_OVERFLOW; 303 1.4 alnsn is_carry = GET_FLAG_TYPE(op) == GET_FLAG_TYPE(SLJIT_SET_CARRY); 304 1.4 alnsn 305 1.1 alnsn if (flags & SRC2_IMM) { 306 1.4 alnsn if (is_overflow) { 307 1.2 alnsn if (src2 >= 0) 308 1.4 alnsn FAIL_IF(push_inst(compiler, OR | S(src1) | T(src1) | DA(EQUAL_FLAG), EQUAL_FLAG)); 309 1.2 alnsn else 310 1.4 alnsn FAIL_IF(push_inst(compiler, NOR | S(src1) | T(src1) | DA(EQUAL_FLAG), EQUAL_FLAG)); 311 1.1 alnsn } 312 1.4 alnsn else if (op & SLJIT_SET_Z) 313 1.1 alnsn FAIL_IF(push_inst(compiler, ADDIU | S(src1) | TA(EQUAL_FLAG) | IMM(-src2), EQUAL_FLAG)); 314 1.4 alnsn 315 1.4 alnsn if (is_overflow || is_carry) 316 1.4 alnsn FAIL_IF(push_inst(compiler, SLTIU | S(src1) | TA(OTHER_FLAG) | IMM(src2), OTHER_FLAG)); 317 1.1 alnsn /* dst may be the same as src1 or src2. */ 318 1.4 alnsn if (!(flags & UNUSED_DEST) || (op & VARIABLE_FLAG_MASK)) 319 1.1 alnsn FAIL_IF(push_inst(compiler, ADDIU | S(src1) | T(dst) | IMM(-src2), DR(dst))); 320 1.1 alnsn } 321 1.1 alnsn else { 322 1.4 alnsn if (is_overflow) 323 1.4 alnsn FAIL_IF(push_inst(compiler, XOR | S(src1) | T(src2) | DA(EQUAL_FLAG), EQUAL_FLAG)); 324 1.4 alnsn else if (op & SLJIT_SET_Z) 325 1.1 alnsn FAIL_IF(push_inst(compiler, SUBU | S(src1) | T(src2) | DA(EQUAL_FLAG), EQUAL_FLAG)); 326 1.4 alnsn 327 1.4 alnsn if (is_overflow || is_carry) 328 1.4 alnsn FAIL_IF(push_inst(compiler, SLTU | S(src1) | T(src2) | DA(OTHER_FLAG), OTHER_FLAG)); 329 1.1 alnsn /* dst may be the same as src1 or src2. */ 330 1.4 alnsn if (!(flags & UNUSED_DEST) || (op & VARIABLE_FLAG_MASK)) 331 1.1 alnsn FAIL_IF(push_inst(compiler, SUBU | S(src1) | T(src2) | D(dst), DR(dst))); 332 1.1 alnsn } 333 1.1 alnsn 334 1.4 alnsn if (!is_overflow) 335 1.2 alnsn return SLJIT_SUCCESS; 336 1.4 alnsn FAIL_IF(push_inst(compiler, SLL | TA(OTHER_FLAG) | D(TMP_REG1) | SH_IMM(31), DR(TMP_REG1))); 337 1.4 alnsn FAIL_IF(push_inst(compiler, XOR | S(TMP_REG1) | TA(EQUAL_FLAG) | DA(EQUAL_FLAG), EQUAL_FLAG)); 338 1.4 alnsn FAIL_IF(push_inst(compiler, XOR | S(dst) | TA(EQUAL_FLAG) | DA(OTHER_FLAG), OTHER_FLAG)); 339 1.4 alnsn if (op & SLJIT_SET_Z) 340 1.4 alnsn FAIL_IF(push_inst(compiler, ADDU | S(dst) | TA(0) | DA(EQUAL_FLAG), EQUAL_FLAG)); 341 1.4 alnsn return push_inst(compiler, SRL | TA(OTHER_FLAG) | DA(OTHER_FLAG) | SH_IMM(31), OTHER_FLAG); 342 1.1 alnsn 343 1.1 alnsn case SLJIT_SUBC: 344 1.1 alnsn if ((flags & SRC2_IMM) && src2 == SIMM_MIN) { 345 1.1 alnsn FAIL_IF(push_inst(compiler, ADDIU | SA(0) | T(TMP_REG2) | IMM(src2), DR(TMP_REG2))); 346 1.1 alnsn src2 = TMP_REG2; 347 1.1 alnsn flags &= ~SRC2_IMM; 348 1.1 alnsn } 349 1.1 alnsn 350 1.4 alnsn is_carry = GET_FLAG_TYPE(op) == GET_FLAG_TYPE(SLJIT_SET_CARRY); 351 1.4 alnsn 352 1.1 alnsn if (flags & SRC2_IMM) { 353 1.4 alnsn if (is_carry) 354 1.4 alnsn FAIL_IF(push_inst(compiler, SLTIU | S(src1) | TA(EQUAL_FLAG) | IMM(src2), EQUAL_FLAG)); 355 1.1 alnsn /* dst may be the same as src1 or src2. */ 356 1.1 alnsn FAIL_IF(push_inst(compiler, ADDIU | S(src1) | T(dst) | IMM(-src2), DR(dst))); 357 1.1 alnsn } 358 1.1 alnsn else { 359 1.4 alnsn if (is_carry) 360 1.4 alnsn FAIL_IF(push_inst(compiler, SLTU | S(src1) | T(src2) | DA(EQUAL_FLAG), EQUAL_FLAG)); 361 1.1 alnsn /* dst may be the same as src1 or src2. */ 362 1.1 alnsn FAIL_IF(push_inst(compiler, SUBU | S(src1) | T(src2) | D(dst), DR(dst))); 363 1.1 alnsn } 364 1.1 alnsn 365 1.4 alnsn if (is_carry) 366 1.4 alnsn FAIL_IF(push_inst(compiler, SLTU | S(dst) | TA(OTHER_FLAG) | D(TMP_REG1), DR(TMP_REG1))); 367 1.1 alnsn 368 1.4 alnsn FAIL_IF(push_inst(compiler, SUBU | S(dst) | TA(OTHER_FLAG) | D(dst), DR(dst))); 369 1.4 alnsn return (is_carry) ? push_inst(compiler, OR | SA(EQUAL_FLAG) | T(TMP_REG1) | DA(OTHER_FLAG), OTHER_FLAG) : SLJIT_SUCCESS; 370 1.1 alnsn 371 1.1 alnsn case SLJIT_MUL: 372 1.1 alnsn SLJIT_ASSERT(!(flags & SRC2_IMM)); 373 1.4 alnsn 374 1.4 alnsn if (GET_FLAG_TYPE(op) != SLJIT_MUL_OVERFLOW && GET_FLAG_TYPE(op) != SLJIT_MUL_NOT_OVERFLOW) { 375 1.3 alnsn #if (defined SLJIT_MIPS_R1 && SLJIT_MIPS_R1) 376 1.1 alnsn return push_inst(compiler, MUL | S(src1) | T(src2) | D(dst), DR(dst)); 377 1.1 alnsn #else 378 1.1 alnsn FAIL_IF(push_inst(compiler, MULT | S(src1) | T(src2), MOVABLE_INS)); 379 1.1 alnsn return push_inst(compiler, MFLO | D(dst), DR(dst)); 380 1.1 alnsn #endif 381 1.1 alnsn } 382 1.1 alnsn FAIL_IF(push_inst(compiler, MULT | S(src1) | T(src2), MOVABLE_INS)); 383 1.4 alnsn FAIL_IF(push_inst(compiler, MFHI | DA(EQUAL_FLAG), EQUAL_FLAG)); 384 1.1 alnsn FAIL_IF(push_inst(compiler, MFLO | D(dst), DR(dst))); 385 1.4 alnsn FAIL_IF(push_inst(compiler, SRA | T(dst) | DA(OTHER_FLAG) | SH_IMM(31), OTHER_FLAG)); 386 1.4 alnsn return push_inst(compiler, SUBU | SA(EQUAL_FLAG) | TA(OTHER_FLAG) | DA(OTHER_FLAG), OTHER_FLAG); 387 1.1 alnsn 388 1.1 alnsn case SLJIT_AND: 389 1.1 alnsn EMIT_LOGICAL(ANDI, AND); 390 1.1 alnsn return SLJIT_SUCCESS; 391 1.1 alnsn 392 1.1 alnsn case SLJIT_OR: 393 1.1 alnsn EMIT_LOGICAL(ORI, OR); 394 1.1 alnsn return SLJIT_SUCCESS; 395 1.1 alnsn 396 1.1 alnsn case SLJIT_XOR: 397 1.1 alnsn EMIT_LOGICAL(XORI, XOR); 398 1.1 alnsn return SLJIT_SUCCESS; 399 1.1 alnsn 400 1.1 alnsn case SLJIT_SHL: 401 1.1 alnsn EMIT_SHIFT(SLL, SLLV); 402 1.1 alnsn return SLJIT_SUCCESS; 403 1.1 alnsn 404 1.1 alnsn case SLJIT_LSHR: 405 1.1 alnsn EMIT_SHIFT(SRL, SRLV); 406 1.1 alnsn return SLJIT_SUCCESS; 407 1.1 alnsn 408 1.1 alnsn case SLJIT_ASHR: 409 1.1 alnsn EMIT_SHIFT(SRA, SRAV); 410 1.1 alnsn return SLJIT_SUCCESS; 411 1.1 alnsn } 412 1.1 alnsn 413 1.4 alnsn SLJIT_UNREACHABLE(); 414 1.1 alnsn return SLJIT_SUCCESS; 415 1.1 alnsn } 416 1.1 alnsn 417 1.3 alnsn static SLJIT_INLINE sljit_s32 emit_const(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw init_value) 418 1.1 alnsn { 419 1.2 alnsn FAIL_IF(push_inst(compiler, LUI | T(dst) | IMM(init_value >> 16), DR(dst))); 420 1.2 alnsn return push_inst(compiler, ORI | S(dst) | T(dst) | IMM(init_value), DR(dst)); 421 1.1 alnsn } 422 1.1 alnsn 423 1.4 alnsn SLJIT_API_FUNC_ATTRIBUTE void sljit_set_jump_addr(sljit_uw addr, sljit_uw new_target, sljit_sw executable_offset) 424 1.1 alnsn { 425 1.4 alnsn sljit_ins *inst = (sljit_ins *)addr; 426 1.1 alnsn 427 1.4 alnsn inst[0] = (inst[0] & 0xffff0000) | ((new_target >> 16) & 0xffff); 428 1.4 alnsn inst[1] = (inst[1] & 0xffff0000) | (new_target & 0xffff); 429 1.4 alnsn inst = (sljit_ins *)SLJIT_ADD_EXEC_OFFSET(inst, executable_offset); 430 1.1 alnsn SLJIT_CACHE_FLUSH(inst, inst + 2); 431 1.1 alnsn } 432 1.1 alnsn 433 1.4 alnsn SLJIT_API_FUNC_ATTRIBUTE void sljit_set_const(sljit_uw addr, sljit_sw new_constant, sljit_sw executable_offset) 434 1.1 alnsn { 435 1.4 alnsn sljit_ins *inst = (sljit_ins *)addr; 436 1.1 alnsn 437 1.1 alnsn inst[0] = (inst[0] & 0xffff0000) | ((new_constant >> 16) & 0xffff); 438 1.1 alnsn inst[1] = (inst[1] & 0xffff0000) | (new_constant & 0xffff); 439 1.4 alnsn inst = (sljit_ins *)SLJIT_ADD_EXEC_OFFSET(inst, executable_offset); 440 1.1 alnsn SLJIT_CACHE_FLUSH(inst, inst + 2); 441 1.1 alnsn } 442