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