1 /* $NetBSD: sljitNativeMIPS_64.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 (at) 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 64-bit arch dependent functions. */ 30 31 static sljit_s32 load_immediate(struct sljit_compiler *compiler, sljit_s32 dst_ar, sljit_sw imm) 32 { 33 sljit_s32 shift = 32; 34 sljit_s32 shift2; 35 sljit_s32 inv = 0; 36 sljit_ins ins; 37 sljit_uw uimm; 38 39 if (!(imm & ~0xffff)) 40 return push_inst(compiler, ORI | SA(0) | TA(dst_ar) | IMM(imm), dst_ar); 41 42 if (imm < 0 && imm >= SIMM_MIN) 43 return push_inst(compiler, ADDIU | SA(0) | TA(dst_ar) | IMM(imm), dst_ar); 44 45 if (imm <= 0x7fffffffl && imm >= -0x80000000l) { 46 FAIL_IF(push_inst(compiler, LUI | TA(dst_ar) | IMM(imm >> 16), dst_ar)); 47 return (imm & 0xffff) ? push_inst(compiler, ORI | SA(dst_ar) | TA(dst_ar) | IMM(imm), dst_ar) : SLJIT_SUCCESS; 48 } 49 50 /* Zero extended number. */ 51 uimm = imm; 52 if (imm < 0) { 53 uimm = ~imm; 54 inv = 1; 55 } 56 57 while (!(uimm & 0xff00000000000000l)) { 58 shift -= 8; 59 uimm <<= 8; 60 } 61 62 if (!(uimm & 0xf000000000000000l)) { 63 shift -= 4; 64 uimm <<= 4; 65 } 66 67 if (!(uimm & 0xc000000000000000l)) { 68 shift -= 2; 69 uimm <<= 2; 70 } 71 72 if ((sljit_sw)uimm < 0) { 73 uimm >>= 1; 74 shift += 1; 75 } 76 SLJIT_ASSERT(((uimm & 0xc000000000000000l) == 0x4000000000000000l) && (shift > 0) && (shift <= 32)); 77 78 if (inv) 79 uimm = ~uimm; 80 81 FAIL_IF(push_inst(compiler, LUI | TA(dst_ar) | IMM(uimm >> 48), dst_ar)); 82 if (uimm & 0x0000ffff00000000l) 83 FAIL_IF(push_inst(compiler, ORI | SA(dst_ar) | TA(dst_ar) | IMM(uimm >> 32), dst_ar)); 84 85 imm &= (1l << shift) - 1; 86 if (!(imm & ~0xffff)) { 87 ins = (shift == 32) ? DSLL32 : DSLL; 88 if (shift < 32) 89 ins |= SH_IMM(shift); 90 FAIL_IF(push_inst(compiler, ins | TA(dst_ar) | DA(dst_ar), dst_ar)); 91 return !(imm & 0xffff) ? SLJIT_SUCCESS : push_inst(compiler, ORI | SA(dst_ar) | TA(dst_ar) | IMM(imm), dst_ar); 92 } 93 94 /* Double shifts needs to be performed. */ 95 uimm <<= 32; 96 shift2 = shift - 16; 97 98 while (!(uimm & 0xf000000000000000l)) { 99 shift2 -= 4; 100 uimm <<= 4; 101 } 102 103 if (!(uimm & 0xc000000000000000l)) { 104 shift2 -= 2; 105 uimm <<= 2; 106 } 107 108 if (!(uimm & 0x8000000000000000l)) { 109 shift2--; 110 uimm <<= 1; 111 } 112 113 SLJIT_ASSERT((uimm & 0x8000000000000000l) && (shift2 > 0) && (shift2 <= 16)); 114 115 FAIL_IF(push_inst(compiler, DSLL | TA(dst_ar) | DA(dst_ar) | SH_IMM(shift - shift2), dst_ar)); 116 FAIL_IF(push_inst(compiler, ORI | SA(dst_ar) | TA(dst_ar) | IMM(uimm >> 48), dst_ar)); 117 FAIL_IF(push_inst(compiler, DSLL | TA(dst_ar) | DA(dst_ar) | SH_IMM(shift2), dst_ar)); 118 119 imm &= (1l << shift2) - 1; 120 return !(imm & 0xffff) ? SLJIT_SUCCESS : push_inst(compiler, ORI | SA(dst_ar) | TA(dst_ar) | IMM(imm), dst_ar); 121 } 122 123 #define SELECT_OP(a, b) \ 124 (!(op & SLJIT_I32_OP) ? a : b) 125 126 #define EMIT_LOGICAL(op_imm, op_norm) \ 127 if (flags & SRC2_IMM) { \ 128 if (op & SLJIT_SET_Z) \ 129 FAIL_IF(push_inst(compiler, op_imm | S(src1) | TA(EQUAL_FLAG) | IMM(src2), EQUAL_FLAG)); \ 130 if (!(flags & UNUSED_DEST)) \ 131 FAIL_IF(push_inst(compiler, op_imm | S(src1) | T(dst) | IMM(src2), DR(dst))); \ 132 } \ 133 else { \ 134 if (op & SLJIT_SET_Z) \ 135 FAIL_IF(push_inst(compiler, op_norm | S(src1) | T(src2) | DA(EQUAL_FLAG), EQUAL_FLAG)); \ 136 if (!(flags & UNUSED_DEST)) \ 137 FAIL_IF(push_inst(compiler, op_norm | S(src1) | T(src2) | D(dst), DR(dst))); \ 138 } 139 140 #define EMIT_SHIFT(op_dimm, op_dimm32, op_imm, op_dv, op_v) \ 141 if (flags & SRC2_IMM) { \ 142 if (src2 >= 32) { \ 143 SLJIT_ASSERT(!(op & SLJIT_I32_OP)); \ 144 ins = op_dimm32; \ 145 src2 -= 32; \ 146 } \ 147 else \ 148 ins = (op & SLJIT_I32_OP) ? op_imm : op_dimm; \ 149 if (op & SLJIT_SET_Z) \ 150 FAIL_IF(push_inst(compiler, ins | T(src1) | DA(EQUAL_FLAG) | SH_IMM(src2), EQUAL_FLAG)); \ 151 if (!(flags & UNUSED_DEST)) \ 152 FAIL_IF(push_inst(compiler, ins | T(src1) | D(dst) | SH_IMM(src2), DR(dst))); \ 153 } \ 154 else { \ 155 ins = (op & SLJIT_I32_OP) ? op_v : op_dv; \ 156 if (op & SLJIT_SET_Z) \ 157 FAIL_IF(push_inst(compiler, ins | S(src2) | T(src1) | DA(EQUAL_FLAG), EQUAL_FLAG)); \ 158 if (!(flags & UNUSED_DEST)) \ 159 FAIL_IF(push_inst(compiler, ins | S(src2) | T(src1) | D(dst), DR(dst))); \ 160 } 161 162 static SLJIT_INLINE sljit_s32 emit_single_op(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 flags, 163 sljit_s32 dst, sljit_s32 src1, sljit_sw src2) 164 { 165 sljit_ins ins; 166 sljit_s32 is_overflow, is_carry, is_handled; 167 168 switch (GET_OPCODE(op)) { 169 case SLJIT_MOV: 170 case SLJIT_MOV_P: 171 SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & SRC2_IMM)); 172 if (dst != src2) 173 return push_inst(compiler, SELECT_OP(DADDU, ADDU) | S(src2) | TA(0) | D(dst), DR(dst)); 174 return SLJIT_SUCCESS; 175 176 case SLJIT_MOV_U8: 177 case SLJIT_MOV_S8: 178 SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & SRC2_IMM)); 179 if ((flags & (REG_DEST | REG2_SOURCE)) == (REG_DEST | REG2_SOURCE)) { 180 if (op == SLJIT_MOV_S8) { 181 FAIL_IF(push_inst(compiler, DSLL32 | T(src2) | D(dst) | SH_IMM(24), DR(dst))); 182 return push_inst(compiler, DSRA32 | T(dst) | D(dst) | SH_IMM(24), DR(dst)); 183 } 184 return push_inst(compiler, ANDI | S(src2) | T(dst) | IMM(0xff), DR(dst)); 185 } 186 else { 187 SLJIT_ASSERT(dst == src2); 188 } 189 return SLJIT_SUCCESS; 190 191 case SLJIT_MOV_U16: 192 case SLJIT_MOV_S16: 193 SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & SRC2_IMM)); 194 if ((flags & (REG_DEST | REG2_SOURCE)) == (REG_DEST | REG2_SOURCE)) { 195 if (op == SLJIT_MOV_S16) { 196 FAIL_IF(push_inst(compiler, DSLL32 | T(src2) | D(dst) | SH_IMM(16), DR(dst))); 197 return push_inst(compiler, DSRA32 | T(dst) | D(dst) | SH_IMM(16), DR(dst)); 198 } 199 return push_inst(compiler, ANDI | S(src2) | T(dst) | IMM(0xffff), DR(dst)); 200 } 201 else { 202 SLJIT_ASSERT(dst == src2); 203 } 204 return SLJIT_SUCCESS; 205 206 case SLJIT_MOV_U32: 207 SLJIT_ASSERT(!(op & SLJIT_I32_OP)); 208 FAIL_IF(push_inst(compiler, DSLL32 | T(src2) | D(dst) | SH_IMM(0), DR(dst))); 209 return push_inst(compiler, DSRL32 | T(dst) | D(dst) | SH_IMM(0), DR(dst)); 210 211 case SLJIT_MOV_S32: 212 SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & SRC2_IMM)); 213 return push_inst(compiler, SLL | T(src2) | D(dst) | SH_IMM(0), DR(dst)); 214 215 case SLJIT_NOT: 216 SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & SRC2_IMM)); 217 if (op & SLJIT_SET_Z) 218 FAIL_IF(push_inst(compiler, NOR | S(src2) | T(src2) | DA(EQUAL_FLAG), EQUAL_FLAG)); 219 if (!(flags & UNUSED_DEST)) 220 FAIL_IF(push_inst(compiler, NOR | S(src2) | T(src2) | D(dst), DR(dst))); 221 return SLJIT_SUCCESS; 222 223 case SLJIT_CLZ: 224 SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & SRC2_IMM)); 225 #if (defined SLJIT_MIPS_R1 && SLJIT_MIPS_R1) 226 if (op & SLJIT_SET_Z) 227 FAIL_IF(push_inst(compiler, SELECT_OP(DCLZ, CLZ) | S(src2) | TA(EQUAL_FLAG) | DA(EQUAL_FLAG), EQUAL_FLAG)); 228 if (!(flags & UNUSED_DEST)) 229 FAIL_IF(push_inst(compiler, SELECT_OP(DCLZ, CLZ) | S(src2) | T(dst) | D(dst), DR(dst))); 230 #else 231 if (SLJIT_UNLIKELY(flags & UNUSED_DEST)) { 232 FAIL_IF(push_inst(compiler, SELECT_OP(DSRL32, SRL) | T(src2) | DA(EQUAL_FLAG) | SH_IMM(31), EQUAL_FLAG)); 233 return push_inst(compiler, XORI | SA(EQUAL_FLAG) | TA(EQUAL_FLAG) | IMM(1), EQUAL_FLAG); 234 } 235 /* Nearly all instructions are unmovable in the following sequence. */ 236 FAIL_IF(push_inst(compiler, SELECT_OP(DADDU, ADDU) | S(src2) | TA(0) | D(TMP_REG1), DR(TMP_REG1))); 237 /* Check zero. */ 238 FAIL_IF(push_inst(compiler, BEQ | S(TMP_REG1) | TA(0) | IMM(5), UNMOVABLE_INS)); 239 FAIL_IF(push_inst(compiler, ORI | SA(0) | T(dst) | IMM((op & SLJIT_I32_OP) ? 32 : 64), UNMOVABLE_INS)); 240 FAIL_IF(push_inst(compiler, SELECT_OP(DADDIU, ADDIU) | SA(0) | T(dst) | IMM(-1), DR(dst))); 241 /* Loop for searching the highest bit. */ 242 FAIL_IF(push_inst(compiler, SELECT_OP(DADDIU, ADDIU) | S(dst) | T(dst) | IMM(1), DR(dst))); 243 FAIL_IF(push_inst(compiler, BGEZ | S(TMP_REG1) | IMM(-2), UNMOVABLE_INS)); 244 FAIL_IF(push_inst(compiler, SELECT_OP(DSLL, SLL) | T(TMP_REG1) | D(TMP_REG1) | SH_IMM(1), UNMOVABLE_INS)); 245 if (op & SLJIT_SET_Z) 246 return push_inst(compiler, SELECT_OP(DADDU, ADDU) | S(dst) | TA(0) | DA(EQUAL_FLAG), EQUAL_FLAG); 247 #endif 248 return SLJIT_SUCCESS; 249 250 case SLJIT_ADD: 251 is_overflow = GET_FLAG_TYPE(op) == SLJIT_OVERFLOW || GET_FLAG_TYPE(op) == SLJIT_NOT_OVERFLOW; 252 is_carry = GET_FLAG_TYPE(op) == GET_FLAG_TYPE(SLJIT_SET_CARRY); 253 254 if (flags & SRC2_IMM) { 255 if (is_overflow) { 256 if (src2 >= 0) 257 FAIL_IF(push_inst(compiler, OR | S(src1) | T(src1) | DA(EQUAL_FLAG), EQUAL_FLAG)); 258 else 259 FAIL_IF(push_inst(compiler, NOR | S(src1) | T(src1) | DA(EQUAL_FLAG), EQUAL_FLAG)); 260 } 261 else if (op & SLJIT_SET_Z) 262 FAIL_IF(push_inst(compiler, SELECT_OP(DADDIU, ADDIU) | S(src1) | TA(EQUAL_FLAG) | IMM(src2), EQUAL_FLAG)); 263 264 if (is_overflow || is_carry) { 265 if (src2 >= 0) 266 FAIL_IF(push_inst(compiler, ORI | S(src1) | TA(OTHER_FLAG) | IMM(src2), OTHER_FLAG)); 267 else { 268 FAIL_IF(push_inst(compiler, SELECT_OP(DADDIU, ADDIU) | SA(0) | TA(OTHER_FLAG) | IMM(src2), OTHER_FLAG)); 269 FAIL_IF(push_inst(compiler, OR | S(src1) | TA(OTHER_FLAG) | DA(OTHER_FLAG), OTHER_FLAG)); 270 } 271 } 272 /* dst may be the same as src1 or src2. */ 273 if (!(flags & UNUSED_DEST) || (op & VARIABLE_FLAG_MASK)) 274 FAIL_IF(push_inst(compiler, SELECT_OP(DADDIU, ADDIU) | S(src1) | T(dst) | IMM(src2), DR(dst))); 275 } 276 else { 277 if (is_overflow) 278 FAIL_IF(push_inst(compiler, XOR | S(src1) | T(src2) | DA(EQUAL_FLAG), EQUAL_FLAG)); 279 else if (op & SLJIT_SET_Z) 280 FAIL_IF(push_inst(compiler, SELECT_OP(DADDU, ADDU) | S(src1) | T(src2) | DA(EQUAL_FLAG), EQUAL_FLAG)); 281 282 if (is_overflow || is_carry) 283 FAIL_IF(push_inst(compiler, OR | S(src1) | T(src2) | DA(OTHER_FLAG), OTHER_FLAG)); 284 /* dst may be the same as src1 or src2. */ 285 if (!(flags & UNUSED_DEST) || (op & VARIABLE_FLAG_MASK)) 286 FAIL_IF(push_inst(compiler, SELECT_OP(DADDU, ADDU) | S(src1) | T(src2) | D(dst), DR(dst))); 287 } 288 289 /* a + b >= a | b (otherwise, the carry should be set to 1). */ 290 if (is_overflow || is_carry) 291 FAIL_IF(push_inst(compiler, SLTU | S(dst) | TA(OTHER_FLAG) | DA(OTHER_FLAG), OTHER_FLAG)); 292 if (!is_overflow) 293 return SLJIT_SUCCESS; 294 FAIL_IF(push_inst(compiler, SELECT_OP(DSLL32, SLL) | TA(OTHER_FLAG) | D(TMP_REG1) | SH_IMM(31), DR(TMP_REG1))); 295 FAIL_IF(push_inst(compiler, XOR | S(TMP_REG1) | TA(EQUAL_FLAG) | DA(EQUAL_FLAG), EQUAL_FLAG)); 296 FAIL_IF(push_inst(compiler, XOR | S(dst) | TA(EQUAL_FLAG) | DA(OTHER_FLAG), OTHER_FLAG)); 297 if (op & SLJIT_SET_Z) 298 FAIL_IF(push_inst(compiler, SELECT_OP(DADDU, ADDU) | S(dst) | TA(0) | DA(EQUAL_FLAG), EQUAL_FLAG)); 299 return push_inst(compiler, SELECT_OP(DSRL32, SRL) | TA(OTHER_FLAG) | DA(OTHER_FLAG) | SH_IMM(31), OTHER_FLAG); 300 301 case SLJIT_ADDC: 302 is_carry = GET_FLAG_TYPE(op) == GET_FLAG_TYPE(SLJIT_SET_CARRY); 303 304 if (flags & SRC2_IMM) { 305 if (is_carry) { 306 if (src2 >= 0) 307 FAIL_IF(push_inst(compiler, ORI | S(src1) | TA(EQUAL_FLAG) | IMM(src2), EQUAL_FLAG)); 308 else { 309 FAIL_IF(push_inst(compiler, SELECT_OP(DADDIU, ADDIU) | SA(0) | TA(EQUAL_FLAG) | IMM(src2), EQUAL_FLAG)); 310 FAIL_IF(push_inst(compiler, OR | S(src1) | TA(EQUAL_FLAG) | DA(EQUAL_FLAG), EQUAL_FLAG)); 311 } 312 } 313 FAIL_IF(push_inst(compiler, SELECT_OP(DADDIU, ADDIU) | S(src1) | T(dst) | IMM(src2), DR(dst))); 314 } else { 315 if (is_carry) 316 FAIL_IF(push_inst(compiler, OR | S(src1) | T(src2) | DA(EQUAL_FLAG), EQUAL_FLAG)); 317 /* dst may be the same as src1 or src2. */ 318 FAIL_IF(push_inst(compiler, SELECT_OP(DADDU, ADDU) | S(src1) | T(src2) | D(dst), DR(dst))); 319 } 320 if (is_carry) 321 FAIL_IF(push_inst(compiler, SLTU | S(dst) | TA(EQUAL_FLAG) | DA(EQUAL_FLAG), EQUAL_FLAG)); 322 323 FAIL_IF(push_inst(compiler, SELECT_OP(DADDU, ADDU) | S(dst) | TA(OTHER_FLAG) | D(dst), DR(dst))); 324 if (!is_carry) 325 return SLJIT_SUCCESS; 326 327 /* Set ULESS_FLAG (dst == 0) && (OTHER_FLAG == 1). */ 328 FAIL_IF(push_inst(compiler, SLTU | S(dst) | TA(OTHER_FLAG) | DA(OTHER_FLAG), OTHER_FLAG)); 329 /* Set carry flag. */ 330 return push_inst(compiler, OR | SA(OTHER_FLAG) | TA(EQUAL_FLAG) | DA(OTHER_FLAG), OTHER_FLAG); 331 332 case SLJIT_SUB: 333 if ((flags & SRC2_IMM) && src2 == SIMM_MIN) { 334 FAIL_IF(push_inst(compiler, ADDIU | SA(0) | T(TMP_REG2) | IMM(src2), DR(TMP_REG2))); 335 src2 = TMP_REG2; 336 flags &= ~SRC2_IMM; 337 } 338 339 is_handled = 0; 340 341 if (flags & SRC2_IMM) { 342 if (GET_FLAG_TYPE(op) == SLJIT_LESS || GET_FLAG_TYPE(op) == SLJIT_GREATER_EQUAL) { 343 FAIL_IF(push_inst(compiler, SLTIU | S(src1) | TA(OTHER_FLAG) | IMM(src2), OTHER_FLAG)); 344 is_handled = 1; 345 } 346 else if (GET_FLAG_TYPE(op) == SLJIT_SIG_LESS || GET_FLAG_TYPE(op) == SLJIT_SIG_GREATER_EQUAL) { 347 FAIL_IF(push_inst(compiler, SLTI | S(src1) | TA(OTHER_FLAG) | IMM(src2), OTHER_FLAG)); 348 is_handled = 1; 349 } 350 } 351 352 if (!is_handled && GET_FLAG_TYPE(op) >= SLJIT_LESS && GET_FLAG_TYPE(op) <= SLJIT_SIG_LESS_EQUAL) { 353 is_handled = 1; 354 355 if (flags & SRC2_IMM) { 356 FAIL_IF(push_inst(compiler, ADDIU | SA(0) | T(TMP_REG2) | IMM(src2), DR(TMP_REG2))); 357 src2 = TMP_REG2; 358 flags &= ~SRC2_IMM; 359 } 360 361 if (GET_FLAG_TYPE(op) == SLJIT_LESS || GET_FLAG_TYPE(op) == SLJIT_GREATER_EQUAL) { 362 FAIL_IF(push_inst(compiler, SLTU | S(src1) | T(src2) | DA(OTHER_FLAG), OTHER_FLAG)); 363 } 364 else if (GET_FLAG_TYPE(op) == SLJIT_GREATER || GET_FLAG_TYPE(op) == SLJIT_LESS_EQUAL) 365 { 366 FAIL_IF(push_inst(compiler, SLTU | S(src2) | T(src1) | DA(OTHER_FLAG), OTHER_FLAG)); 367 } 368 else if (GET_FLAG_TYPE(op) == SLJIT_SIG_LESS || GET_FLAG_TYPE(op) == SLJIT_SIG_GREATER_EQUAL) { 369 FAIL_IF(push_inst(compiler, SLT | S(src1) | T(src2) | DA(OTHER_FLAG), OTHER_FLAG)); 370 } 371 else if (GET_FLAG_TYPE(op) == SLJIT_SIG_GREATER || GET_FLAG_TYPE(op) == SLJIT_SIG_LESS_EQUAL) 372 { 373 FAIL_IF(push_inst(compiler, SLT | S(src2) | T(src1) | DA(OTHER_FLAG), OTHER_FLAG)); 374 } 375 } 376 377 if (is_handled) { 378 if (flags & SRC2_IMM) { 379 if (op & SLJIT_SET_Z) 380 FAIL_IF(push_inst(compiler, SELECT_OP(DADDIU, ADDIU) | S(src1) | TA(EQUAL_FLAG) | IMM(-src2), EQUAL_FLAG)); 381 if (!(flags & UNUSED_DEST)) 382 return push_inst(compiler, SELECT_OP(DADDIU, ADDIU) | S(src1) | T(dst) | IMM(-src2), DR(dst)); 383 } 384 else { 385 if (op & SLJIT_SET_Z) 386 FAIL_IF(push_inst(compiler, SELECT_OP(DSUBU, SUBU) | S(src1) | T(src2) | DA(EQUAL_FLAG), EQUAL_FLAG)); 387 if (!(flags & UNUSED_DEST)) 388 return push_inst(compiler, SELECT_OP(DSUBU, SUBU) | S(src1) | T(src2) | D(dst), DR(dst)); 389 } 390 return SLJIT_SUCCESS; 391 } 392 393 is_overflow = GET_FLAG_TYPE(op) == SLJIT_OVERFLOW || GET_FLAG_TYPE(op) == SLJIT_NOT_OVERFLOW; 394 is_carry = GET_FLAG_TYPE(op) == GET_FLAG_TYPE(SLJIT_SET_CARRY); 395 396 if (flags & SRC2_IMM) { 397 if (is_overflow) { 398 if (src2 >= 0) 399 FAIL_IF(push_inst(compiler, OR | S(src1) | T(src1) | DA(EQUAL_FLAG), EQUAL_FLAG)); 400 else 401 FAIL_IF(push_inst(compiler, NOR | S(src1) | T(src1) | DA(EQUAL_FLAG), EQUAL_FLAG)); 402 } 403 else if (op & SLJIT_SET_Z) 404 FAIL_IF(push_inst(compiler, SELECT_OP(DADDIU, ADDIU) | S(src1) | TA(EQUAL_FLAG) | IMM(-src2), EQUAL_FLAG)); 405 406 if (is_overflow || is_carry) 407 FAIL_IF(push_inst(compiler, SLTIU | S(src1) | TA(OTHER_FLAG) | IMM(src2), OTHER_FLAG)); 408 /* dst may be the same as src1 or src2. */ 409 if (!(flags & UNUSED_DEST) || (op & VARIABLE_FLAG_MASK)) 410 FAIL_IF(push_inst(compiler, SELECT_OP(DADDIU, ADDIU) | S(src1) | T(dst) | IMM(-src2), DR(dst))); 411 } 412 else { 413 if (is_overflow) 414 FAIL_IF(push_inst(compiler, XOR | S(src1) | T(src2) | DA(EQUAL_FLAG), EQUAL_FLAG)); 415 else if (op & SLJIT_SET_Z) 416 FAIL_IF(push_inst(compiler, SELECT_OP(DSUBU, SUBU) | S(src1) | T(src2) | DA(EQUAL_FLAG), EQUAL_FLAG)); 417 418 if (is_overflow || is_carry) 419 FAIL_IF(push_inst(compiler, SLTU | S(src1) | T(src2) | DA(OTHER_FLAG), OTHER_FLAG)); 420 /* dst may be the same as src1 or src2. */ 421 if (!(flags & UNUSED_DEST) || (op & VARIABLE_FLAG_MASK)) 422 FAIL_IF(push_inst(compiler, SELECT_OP(DSUBU, SUBU) | S(src1) | T(src2) | D(dst), DR(dst))); 423 } 424 425 if (!is_overflow) 426 return SLJIT_SUCCESS; 427 FAIL_IF(push_inst(compiler, SELECT_OP(DSLL32, SLL) | TA(OTHER_FLAG) | D(TMP_REG1) | SH_IMM(31), DR(TMP_REG1))); 428 FAIL_IF(push_inst(compiler, XOR | S(TMP_REG1) | TA(EQUAL_FLAG) | DA(EQUAL_FLAG), EQUAL_FLAG)); 429 FAIL_IF(push_inst(compiler, XOR | S(dst) | TA(EQUAL_FLAG) | DA(OTHER_FLAG), OTHER_FLAG)); 430 if (op & SLJIT_SET_Z) 431 FAIL_IF(push_inst(compiler, SELECT_OP(DADDU, ADDU) | S(dst) | TA(0) | DA(EQUAL_FLAG), EQUAL_FLAG)); 432 return push_inst(compiler, SELECT_OP(DSRL32, SRL) | TA(OTHER_FLAG) | DA(OTHER_FLAG) | SH_IMM(31), OTHER_FLAG); 433 434 case SLJIT_SUBC: 435 if ((flags & SRC2_IMM) && src2 == SIMM_MIN) { 436 FAIL_IF(push_inst(compiler, ADDIU | SA(0) | T(TMP_REG2) | IMM(src2), DR(TMP_REG2))); 437 src2 = TMP_REG2; 438 flags &= ~SRC2_IMM; 439 } 440 441 is_carry = GET_FLAG_TYPE(op) == GET_FLAG_TYPE(SLJIT_SET_CARRY); 442 443 if (flags & SRC2_IMM) { 444 if (is_carry) 445 FAIL_IF(push_inst(compiler, SLTIU | S(src1) | TA(EQUAL_FLAG) | IMM(src2), EQUAL_FLAG)); 446 /* dst may be the same as src1 or src2. */ 447 FAIL_IF(push_inst(compiler, SELECT_OP(DADDIU, ADDIU) | S(src1) | T(dst) | IMM(-src2), DR(dst))); 448 } 449 else { 450 if (is_carry) 451 FAIL_IF(push_inst(compiler, SLTU | S(src1) | T(src2) | DA(EQUAL_FLAG), EQUAL_FLAG)); 452 /* dst may be the same as src1 or src2. */ 453 FAIL_IF(push_inst(compiler, SELECT_OP(DSUBU, SUBU) | S(src1) | T(src2) | D(dst), DR(dst))); 454 } 455 456 if (is_carry) 457 FAIL_IF(push_inst(compiler, SLTU | S(dst) | TA(OTHER_FLAG) | D(TMP_REG1), DR(TMP_REG1))); 458 459 FAIL_IF(push_inst(compiler, SELECT_OP(DSUBU, SUBU) | S(dst) | TA(OTHER_FLAG) | D(dst), DR(dst))); 460 return (is_carry) ? push_inst(compiler, OR | SA(EQUAL_FLAG) | T(TMP_REG1) | DA(OTHER_FLAG), OTHER_FLAG) : SLJIT_SUCCESS; 461 462 case SLJIT_MUL: 463 SLJIT_ASSERT(!(flags & SRC2_IMM)); 464 465 if (GET_FLAG_TYPE(op) != SLJIT_MUL_OVERFLOW && GET_FLAG_TYPE(op) != SLJIT_MUL_NOT_OVERFLOW) { 466 #if (defined SLJIT_MIPS_R1 && SLJIT_MIPS_R1) 467 if (op & SLJIT_I32_OP) 468 return push_inst(compiler, MUL | S(src1) | T(src2) | D(dst), DR(dst)); 469 FAIL_IF(push_inst(compiler, DMULT | S(src1) | T(src2), MOVABLE_INS)); 470 return push_inst(compiler, MFLO | D(dst), DR(dst)); 471 #else 472 FAIL_IF(push_inst(compiler, SELECT_OP(DMULT, MULT) | S(src1) | T(src2), MOVABLE_INS)); 473 return push_inst(compiler, MFLO | D(dst), DR(dst)); 474 #endif 475 } 476 FAIL_IF(push_inst(compiler, SELECT_OP(DMULT, MULT) | S(src1) | T(src2), MOVABLE_INS)); 477 FAIL_IF(push_inst(compiler, MFHI | DA(EQUAL_FLAG), EQUAL_FLAG)); 478 FAIL_IF(push_inst(compiler, MFLO | D(dst), DR(dst))); 479 FAIL_IF(push_inst(compiler, SELECT_OP(DSRA32, SRA) | T(dst) | DA(OTHER_FLAG) | SH_IMM(31), OTHER_FLAG)); 480 return push_inst(compiler, SELECT_OP(DSUBU, SUBU) | SA(EQUAL_FLAG) | TA(OTHER_FLAG) | DA(OTHER_FLAG), OTHER_FLAG); 481 482 case SLJIT_AND: 483 EMIT_LOGICAL(ANDI, AND); 484 return SLJIT_SUCCESS; 485 486 case SLJIT_OR: 487 EMIT_LOGICAL(ORI, OR); 488 return SLJIT_SUCCESS; 489 490 case SLJIT_XOR: 491 EMIT_LOGICAL(XORI, XOR); 492 return SLJIT_SUCCESS; 493 494 case SLJIT_SHL: 495 EMIT_SHIFT(DSLL, DSLL32, SLL, DSLLV, SLLV); 496 return SLJIT_SUCCESS; 497 498 case SLJIT_LSHR: 499 EMIT_SHIFT(DSRL, DSRL32, SRL, DSRLV, SRLV); 500 return SLJIT_SUCCESS; 501 502 case SLJIT_ASHR: 503 EMIT_SHIFT(DSRA, DSRA32, SRA, DSRAV, SRAV); 504 return SLJIT_SUCCESS; 505 } 506 507 SLJIT_UNREACHABLE(); 508 return SLJIT_SUCCESS; 509 } 510 511 static SLJIT_INLINE sljit_s32 emit_const(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw init_value) 512 { 513 FAIL_IF(push_inst(compiler, LUI | T(dst) | IMM(init_value >> 48), DR(dst))); 514 FAIL_IF(push_inst(compiler, ORI | S(dst) | T(dst) | IMM(init_value >> 32), DR(dst))); 515 FAIL_IF(push_inst(compiler, DSLL | T(dst) | D(dst) | SH_IMM(16), DR(dst))); 516 FAIL_IF(push_inst(compiler, ORI | S(dst) | T(dst) | IMM(init_value >> 16), DR(dst))); 517 FAIL_IF(push_inst(compiler, DSLL | T(dst) | D(dst) | SH_IMM(16), DR(dst))); 518 return push_inst(compiler, ORI | S(dst) | T(dst) | IMM(init_value), DR(dst)); 519 } 520 521 SLJIT_API_FUNC_ATTRIBUTE void sljit_set_jump_addr(sljit_uw addr, sljit_uw new_target, sljit_sw executable_offset) 522 { 523 sljit_ins *inst = (sljit_ins *)addr; 524 525 inst[0] = (inst[0] & 0xffff0000) | ((new_target >> 48) & 0xffff); 526 inst[1] = (inst[1] & 0xffff0000) | ((new_target >> 32) & 0xffff); 527 inst[3] = (inst[3] & 0xffff0000) | ((new_target >> 16) & 0xffff); 528 inst[5] = (inst[5] & 0xffff0000) | (new_target & 0xffff); 529 inst = (sljit_ins *)SLJIT_ADD_EXEC_OFFSET(inst, executable_offset); 530 SLJIT_CACHE_FLUSH(inst, inst + 6); 531 } 532 533 SLJIT_API_FUNC_ATTRIBUTE void sljit_set_const(sljit_uw addr, sljit_sw new_constant, sljit_sw executable_offset) 534 { 535 sljit_ins *inst = (sljit_ins *)addr; 536 537 inst[0] = (inst[0] & 0xffff0000) | ((new_constant >> 48) & 0xffff); 538 inst[1] = (inst[1] & 0xffff0000) | ((new_constant >> 32) & 0xffff); 539 inst[3] = (inst[3] & 0xffff0000) | ((new_constant >> 16) & 0xffff); 540 inst[5] = (inst[5] & 0xffff0000) | (new_constant & 0xffff); 541 inst = (sljit_ins *)SLJIT_ADD_EXEC_OFFSET(inst, executable_offset); 542 SLJIT_CACHE_FLUSH(inst, inst + 6); 543 } 544