1 /* $NetBSD: sljitNativeMIPS_64.c,v 1.2 2014/06/17 19:33:20 alnsn Exp $ */ 2 3 /* 4 * Stack-less Just-In-Time compiler 5 * 6 * Copyright 2009-2012 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 64-bit arch dependent functions. */ 30 31 static sljit_si load_immediate(struct sljit_compiler *compiler, sljit_si dst_ar, sljit_sw imm) 32 { 33 sljit_si shift = 32; 34 sljit_si shift2; 35 sljit_si 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_INT_OP) ? a : b) 125 126 #define EMIT_LOGICAL(op_imm, op_norm) \ 127 if (flags & SRC2_IMM) { \ 128 if (op & SLJIT_SET_E) \ 129 FAIL_IF(push_inst(compiler, op_imm | S(src1) | TA(EQUAL_FLAG) | IMM(src2), EQUAL_FLAG)); \ 130 if (CHECK_FLAGS(SLJIT_SET_E)) \ 131 FAIL_IF(push_inst(compiler, op_imm | S(src1) | T(dst) | IMM(src2), DR(dst))); \ 132 } \ 133 else { \ 134 if (op & SLJIT_SET_E) \ 135 FAIL_IF(push_inst(compiler, op_norm | S(src1) | T(src2) | DA(EQUAL_FLAG), EQUAL_FLAG)); \ 136 if (CHECK_FLAGS(SLJIT_SET_E)) \ 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_INT_OP)); \ 144 ins = op_dimm32; \ 145 src2 -= 32; \ 146 } \ 147 else \ 148 ins = (op & SLJIT_INT_OP) ? op_imm : op_dimm; \ 149 if (op & SLJIT_SET_E) \ 150 FAIL_IF(push_inst(compiler, ins | T(src1) | DA(EQUAL_FLAG) | SH_IMM(src2), EQUAL_FLAG)); \ 151 if (CHECK_FLAGS(SLJIT_SET_E)) \ 152 FAIL_IF(push_inst(compiler, ins | T(src1) | D(dst) | SH_IMM(src2), DR(dst))); \ 153 } \ 154 else { \ 155 ins = (op & SLJIT_INT_OP) ? op_v : op_dv; \ 156 if (op & SLJIT_SET_E) \ 157 FAIL_IF(push_inst(compiler, ins | S(src2) | T(src1) | DA(EQUAL_FLAG), EQUAL_FLAG)); \ 158 if (CHECK_FLAGS(SLJIT_SET_E)) \ 159 FAIL_IF(push_inst(compiler, ins | S(src2) | T(src1) | D(dst), DR(dst))); \ 160 } 161 162 static SLJIT_INLINE sljit_si emit_single_op(struct sljit_compiler *compiler, sljit_si op, sljit_si flags, 163 sljit_si dst, sljit_si src1, sljit_sw src2) 164 { 165 sljit_ins ins; 166 167 switch (GET_OPCODE(op)) { 168 case SLJIT_MOV: 169 case SLJIT_MOV_P: 170 SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & SRC2_IMM)); 171 if (dst != src2) 172 return push_inst(compiler, SELECT_OP(DADDU, ADDU) | S(src2) | TA(0) | D(dst), DR(dst)); 173 return SLJIT_SUCCESS; 174 175 case SLJIT_MOV_UB: 176 case SLJIT_MOV_SB: 177 SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & SRC2_IMM)); 178 if ((flags & (REG_DEST | REG2_SOURCE)) == (REG_DEST | REG2_SOURCE)) { 179 if (op == SLJIT_MOV_SB) { 180 FAIL_IF(push_inst(compiler, DSLL32 | T(src2) | D(dst) | SH_IMM(24), DR(dst))); 181 return push_inst(compiler, DSRA32 | T(dst) | D(dst) | SH_IMM(24), DR(dst)); 182 } 183 return push_inst(compiler, ANDI | S(src2) | T(dst) | IMM(0xff), DR(dst)); 184 } 185 else if (dst != src2) 186 SLJIT_ASSERT_STOP(); 187 return SLJIT_SUCCESS; 188 189 case SLJIT_MOV_UH: 190 case SLJIT_MOV_SH: 191 SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & SRC2_IMM)); 192 if ((flags & (REG_DEST | REG2_SOURCE)) == (REG_DEST | REG2_SOURCE)) { 193 if (op == SLJIT_MOV_SH) { 194 FAIL_IF(push_inst(compiler, DSLL32 | T(src2) | D(dst) | SH_IMM(16), DR(dst))); 195 return push_inst(compiler, DSRA32 | T(dst) | D(dst) | SH_IMM(16), DR(dst)); 196 } 197 return push_inst(compiler, ANDI | S(src2) | T(dst) | IMM(0xffff), DR(dst)); 198 } 199 else if (dst != src2) 200 SLJIT_ASSERT_STOP(); 201 return SLJIT_SUCCESS; 202 203 case SLJIT_MOV_UI: 204 SLJIT_ASSERT(!(op & SLJIT_INT_OP)); 205 FAIL_IF(push_inst(compiler, DSLL32 | T(src2) | D(dst) | SH_IMM(0), DR(dst))); 206 return push_inst(compiler, DSRL32 | T(dst) | D(dst) | SH_IMM(0), DR(dst)); 207 208 case SLJIT_MOV_SI: 209 SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & SRC2_IMM)); 210 return push_inst(compiler, SLL | T(src2) | D(dst) | SH_IMM(0), DR(dst)); 211 212 case SLJIT_NOT: 213 SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & SRC2_IMM)); 214 if (op & SLJIT_SET_E) 215 FAIL_IF(push_inst(compiler, NOR | S(src2) | T(src2) | DA(EQUAL_FLAG), EQUAL_FLAG)); 216 if (CHECK_FLAGS(SLJIT_SET_E)) 217 FAIL_IF(push_inst(compiler, NOR | S(src2) | T(src2) | D(dst), DR(dst))); 218 return SLJIT_SUCCESS; 219 220 case SLJIT_CLZ: 221 SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & SRC2_IMM)); 222 #if (defined SLJIT_MIPS_32_64 && SLJIT_MIPS_32_64) 223 if (op & SLJIT_SET_E) 224 FAIL_IF(push_inst(compiler, SELECT_OP(DCLZ, CLZ) | S(src2) | TA(EQUAL_FLAG) | DA(EQUAL_FLAG), EQUAL_FLAG)); 225 if (CHECK_FLAGS(SLJIT_SET_E)) 226 FAIL_IF(push_inst(compiler, SELECT_OP(DCLZ, CLZ) | S(src2) | T(dst) | D(dst), DR(dst))); 227 #else 228 if (SLJIT_UNLIKELY(flags & UNUSED_DEST)) { 229 FAIL_IF(push_inst(compiler, SELECT_OP(DSRL32, SRL) | T(src2) | DA(EQUAL_FLAG) | SH_IMM(31), EQUAL_FLAG)); 230 return push_inst(compiler, XORI | SA(EQUAL_FLAG) | TA(EQUAL_FLAG) | IMM(1), EQUAL_FLAG); 231 } 232 /* Nearly all instructions are unmovable in the following sequence. */ 233 FAIL_IF(push_inst(compiler, SELECT_OP(DADDU, ADDU) | S(src2) | TA(0) | D(TMP_REG1), DR(TMP_REG1))); 234 /* Check zero. */ 235 FAIL_IF(push_inst(compiler, BEQ | S(TMP_REG1) | TA(0) | IMM(5), UNMOVABLE_INS)); 236 FAIL_IF(push_inst(compiler, ORI | SA(0) | T(dst) | IMM((op & SLJIT_INT_OP) ? 32 : 64), UNMOVABLE_INS)); 237 FAIL_IF(push_inst(compiler, SELECT_OP(DADDIU, ADDIU) | SA(0) | T(dst) | IMM(-1), DR(dst))); 238 /* Loop for searching the highest bit. */ 239 FAIL_IF(push_inst(compiler, SELECT_OP(DADDIU, ADDIU) | S(dst) | T(dst) | IMM(1), DR(dst))); 240 FAIL_IF(push_inst(compiler, BGEZ | S(TMP_REG1) | IMM(-2), UNMOVABLE_INS)); 241 FAIL_IF(push_inst(compiler, SELECT_OP(DSLL, SLL) | T(TMP_REG1) | D(TMP_REG1) | SH_IMM(1), UNMOVABLE_INS)); 242 if (op & SLJIT_SET_E) 243 return push_inst(compiler, SELECT_OP(DADDU, ADDU) | S(dst) | TA(0) | DA(EQUAL_FLAG), EQUAL_FLAG); 244 #endif 245 return SLJIT_SUCCESS; 246 247 case SLJIT_ADD: 248 if (flags & SRC2_IMM) { 249 if (op & SLJIT_SET_O) { 250 if (src2 >= 0) 251 FAIL_IF(push_inst(compiler, OR | S(src1) | T(src1) | DA(TMP_EREG1), TMP_EREG1)); 252 else 253 FAIL_IF(push_inst(compiler, NOR | S(src1) | T(src1) | DA(TMP_EREG1), TMP_EREG1)); 254 } 255 if (op & SLJIT_SET_E) 256 FAIL_IF(push_inst(compiler, SELECT_OP(DADDIU, ADDIU) | S(src1) | TA(EQUAL_FLAG) | IMM(src2), EQUAL_FLAG)); 257 if (op & (SLJIT_SET_C | SLJIT_SET_O)) { 258 if (src2 >= 0) 259 FAIL_IF(push_inst(compiler, ORI | S(src1) | TA(ULESS_FLAG) | IMM(src2), ULESS_FLAG)); 260 else { 261 FAIL_IF(push_inst(compiler, SELECT_OP(DADDIU, ADDIU) | SA(0) | TA(ULESS_FLAG) | IMM(src2), ULESS_FLAG)); 262 FAIL_IF(push_inst(compiler, OR | S(src1) | TA(ULESS_FLAG) | DA(ULESS_FLAG), ULESS_FLAG)); 263 } 264 } 265 /* dst may be the same as src1 or src2. */ 266 if (CHECK_FLAGS(SLJIT_SET_E)) 267 FAIL_IF(push_inst(compiler, SELECT_OP(DADDIU, ADDIU) | S(src1) | T(dst) | IMM(src2), DR(dst))); 268 } 269 else { 270 if (op & SLJIT_SET_O) 271 FAIL_IF(push_inst(compiler, XOR | S(src1) | T(src2) | DA(TMP_EREG1), TMP_EREG1)); 272 if (op & SLJIT_SET_E) 273 FAIL_IF(push_inst(compiler, SELECT_OP(DADDU, ADDU) | S(src1) | T(src2) | DA(EQUAL_FLAG), EQUAL_FLAG)); 274 if (op & (SLJIT_SET_C | SLJIT_SET_O)) 275 FAIL_IF(push_inst(compiler, OR | S(src1) | T(src2) | DA(ULESS_FLAG), ULESS_FLAG)); 276 /* dst may be the same as src1 or src2. */ 277 if (CHECK_FLAGS(SLJIT_SET_E)) 278 FAIL_IF(push_inst(compiler, SELECT_OP(DADDU, ADDU) | S(src1) | T(src2) | D(dst), DR(dst))); 279 } 280 281 /* a + b >= a | b (otherwise, the carry should be set to 1). */ 282 if (op & (SLJIT_SET_C | SLJIT_SET_O)) 283 FAIL_IF(push_inst(compiler, SLTU | S(dst) | TA(ULESS_FLAG) | DA(ULESS_FLAG), ULESS_FLAG)); 284 if (!(op & SLJIT_SET_O)) 285 return SLJIT_SUCCESS; 286 FAIL_IF(push_inst(compiler, SELECT_OP(DSLL32, SLL) | TA(ULESS_FLAG) | DA(OVERFLOW_FLAG) | SH_IMM(31), OVERFLOW_FLAG)); 287 FAIL_IF(push_inst(compiler, XOR | SA(TMP_EREG1) | TA(OVERFLOW_FLAG) | DA(OVERFLOW_FLAG), OVERFLOW_FLAG)); 288 FAIL_IF(push_inst(compiler, XOR | S(dst) | TA(OVERFLOW_FLAG) | DA(OVERFLOW_FLAG), OVERFLOW_FLAG)); 289 return push_inst(compiler, SELECT_OP(DSRL32, SLL) | TA(OVERFLOW_FLAG) | DA(OVERFLOW_FLAG) | SH_IMM(31), OVERFLOW_FLAG); 290 291 case SLJIT_ADDC: 292 if (flags & SRC2_IMM) { 293 if (op & SLJIT_SET_C) { 294 if (src2 >= 0) 295 FAIL_IF(push_inst(compiler, ORI | S(src1) | TA(TMP_EREG1) | IMM(src2), TMP_EREG1)); 296 else { 297 FAIL_IF(push_inst(compiler, SELECT_OP(DADDIU, ADDIU) | SA(0) | TA(TMP_EREG1) | IMM(src2), TMP_EREG1)); 298 FAIL_IF(push_inst(compiler, OR | S(src1) | TA(TMP_EREG1) | DA(TMP_EREG1), TMP_EREG1)); 299 } 300 } 301 FAIL_IF(push_inst(compiler, SELECT_OP(DADDIU, ADDIU) | S(src1) | T(dst) | IMM(src2), DR(dst))); 302 } else { 303 if (op & SLJIT_SET_C) 304 FAIL_IF(push_inst(compiler, OR | S(src1) | T(src2) | DA(TMP_EREG1), TMP_EREG1)); 305 /* dst may be the same as src1 or src2. */ 306 FAIL_IF(push_inst(compiler, SELECT_OP(DADDU, ADDU) | S(src1) | T(src2) | D(dst), DR(dst))); 307 } 308 if (op & SLJIT_SET_C) 309 FAIL_IF(push_inst(compiler, SLTU | S(dst) | TA(TMP_EREG1) | DA(TMP_EREG1), TMP_EREG1)); 310 311 FAIL_IF(push_inst(compiler, SELECT_OP(DADDU, ADDU) | S(dst) | TA(ULESS_FLAG) | D(dst), DR(dst))); 312 if (!(op & SLJIT_SET_C)) 313 return SLJIT_SUCCESS; 314 315 /* Set ULESS_FLAG (dst == 0) && (ULESS_FLAG == 1). */ 316 FAIL_IF(push_inst(compiler, SLTU | S(dst) | TA(ULESS_FLAG) | DA(ULESS_FLAG), ULESS_FLAG)); 317 /* Set carry flag. */ 318 return push_inst(compiler, OR | SA(ULESS_FLAG) | TA(TMP_EREG1) | DA(ULESS_FLAG), ULESS_FLAG); 319 320 case SLJIT_SUB: 321 if ((flags & SRC2_IMM) && ((op & (SLJIT_SET_U | SLJIT_SET_S)) || src2 == SIMM_MIN)) { 322 FAIL_IF(push_inst(compiler, ADDIU | SA(0) | T(TMP_REG2) | IMM(src2), DR(TMP_REG2))); 323 src2 = TMP_REG2; 324 flags &= ~SRC2_IMM; 325 } 326 327 if (flags & SRC2_IMM) { 328 if (op & SLJIT_SET_O) { 329 if (src2 >= 0) 330 FAIL_IF(push_inst(compiler, OR | S(src1) | T(src1) | DA(TMP_EREG1), TMP_EREG1)); 331 else 332 FAIL_IF(push_inst(compiler, NOR | S(src1) | T(src1) | DA(TMP_EREG1), TMP_EREG1)); 333 } 334 if (op & SLJIT_SET_E) 335 FAIL_IF(push_inst(compiler, SELECT_OP(DADDIU, ADDIU) | S(src1) | TA(EQUAL_FLAG) | IMM(-src2), EQUAL_FLAG)); 336 if (op & (SLJIT_SET_C | SLJIT_SET_O)) 337 FAIL_IF(push_inst(compiler, SLTIU | S(src1) | TA(ULESS_FLAG) | IMM(src2), ULESS_FLAG)); 338 /* dst may be the same as src1 or src2. */ 339 if (CHECK_FLAGS(SLJIT_SET_E)) 340 FAIL_IF(push_inst(compiler, SELECT_OP(DADDIU, ADDIU) | S(src1) | T(dst) | IMM(-src2), DR(dst))); 341 } 342 else { 343 if (op & SLJIT_SET_O) 344 FAIL_IF(push_inst(compiler, XOR | S(src1) | T(src2) | DA(TMP_EREG1), TMP_EREG1)); 345 if (op & SLJIT_SET_E) 346 FAIL_IF(push_inst(compiler, SELECT_OP(DSUBU, SUBU) | S(src1) | T(src2) | DA(EQUAL_FLAG), EQUAL_FLAG)); 347 if (op & (SLJIT_SET_U | SLJIT_SET_C | SLJIT_SET_O)) 348 FAIL_IF(push_inst(compiler, SLTU | S(src1) | T(src2) | DA(ULESS_FLAG), ULESS_FLAG)); 349 if (op & SLJIT_SET_U) 350 FAIL_IF(push_inst(compiler, SLTU | S(src2) | T(src1) | DA(UGREATER_FLAG), UGREATER_FLAG)); 351 if (op & SLJIT_SET_S) { 352 FAIL_IF(push_inst(compiler, SLT | S(src1) | T(src2) | DA(LESS_FLAG), LESS_FLAG)); 353 FAIL_IF(push_inst(compiler, SLT | S(src2) | T(src1) | DA(GREATER_FLAG), GREATER_FLAG)); 354 } 355 /* dst may be the same as src1 or src2. */ 356 if (CHECK_FLAGS(SLJIT_SET_E | SLJIT_SET_U | SLJIT_SET_S | SLJIT_SET_C)) 357 FAIL_IF(push_inst(compiler, SELECT_OP(DSUBU, SUBU) | S(src1) | T(src2) | D(dst), DR(dst))); 358 } 359 360 if (!(op & SLJIT_SET_O)) 361 return SLJIT_SUCCESS; 362 FAIL_IF(push_inst(compiler, SELECT_OP(DSLL32, SLL) | TA(ULESS_FLAG) | DA(OVERFLOW_FLAG) | SH_IMM(31), OVERFLOW_FLAG)); 363 FAIL_IF(push_inst(compiler, XOR | SA(TMP_EREG1) | TA(OVERFLOW_FLAG) | DA(OVERFLOW_FLAG), OVERFLOW_FLAG)); 364 FAIL_IF(push_inst(compiler, XOR | S(dst) | TA(OVERFLOW_FLAG) | DA(OVERFLOW_FLAG), OVERFLOW_FLAG)); 365 return push_inst(compiler, SELECT_OP(DSRL32, SRL) | TA(OVERFLOW_FLAG) | DA(OVERFLOW_FLAG) | SH_IMM(31), OVERFLOW_FLAG); 366 367 case SLJIT_SUBC: 368 if ((flags & SRC2_IMM) && src2 == SIMM_MIN) { 369 FAIL_IF(push_inst(compiler, ADDIU | SA(0) | T(TMP_REG2) | IMM(src2), DR(TMP_REG2))); 370 src2 = TMP_REG2; 371 flags &= ~SRC2_IMM; 372 } 373 374 if (flags & SRC2_IMM) { 375 if (op & SLJIT_SET_C) 376 FAIL_IF(push_inst(compiler, SLTIU | S(src1) | TA(TMP_EREG1) | IMM(src2), TMP_EREG1)); 377 /* dst may be the same as src1 or src2. */ 378 FAIL_IF(push_inst(compiler, SELECT_OP(DADDIU, ADDIU) | S(src1) | T(dst) | IMM(-src2), DR(dst))); 379 } 380 else { 381 if (op & SLJIT_SET_C) 382 FAIL_IF(push_inst(compiler, SLTU | S(src1) | T(src2) | DA(TMP_EREG1), TMP_EREG1)); 383 /* dst may be the same as src1 or src2. */ 384 FAIL_IF(push_inst(compiler, SELECT_OP(DSUBU, SUBU) | S(src1) | T(src2) | D(dst), DR(dst))); 385 } 386 387 if (op & SLJIT_SET_C) 388 FAIL_IF(push_inst(compiler, SLTU | S(dst) | TA(ULESS_FLAG) | DA(TMP_EREG2), TMP_EREG2)); 389 390 FAIL_IF(push_inst(compiler, SELECT_OP(DSUBU, SUBU) | S(dst) | TA(ULESS_FLAG) | D(dst), DR(dst))); 391 return (op & SLJIT_SET_C) ? push_inst(compiler, OR | SA(TMP_EREG1) | TA(TMP_EREG2) | DA(ULESS_FLAG), ULESS_FLAG) : SLJIT_SUCCESS; 392 393 case SLJIT_MUL: 394 SLJIT_ASSERT(!(flags & SRC2_IMM)); 395 if (!(op & SLJIT_SET_O)) { 396 #if (defined SLJIT_MIPS_32_64 && SLJIT_MIPS_32_64) 397 if (op & SLJIT_INT_OP) 398 return push_inst(compiler, MUL | S(src1) | T(src2) | D(dst), DR(dst)); 399 FAIL_IF(push_inst(compiler, DMULT | S(src1) | T(src2), MOVABLE_INS)); 400 return push_inst(compiler, MFLO | D(dst), DR(dst)); 401 #else 402 FAIL_IF(push_inst(compiler, SELECT_OP(DMULT, MULT) | S(src1) | T(src2), MOVABLE_INS)); 403 return push_inst(compiler, MFLO | D(dst), DR(dst)); 404 #endif 405 } 406 FAIL_IF(push_inst(compiler, SELECT_OP(DMULT, MULT) | S(src1) | T(src2), MOVABLE_INS)); 407 FAIL_IF(push_inst(compiler, MFHI | DA(TMP_EREG1), TMP_EREG1)); 408 FAIL_IF(push_inst(compiler, MFLO | D(dst), DR(dst))); 409 FAIL_IF(push_inst(compiler, SELECT_OP(DSRA32, SRA) | T(dst) | DA(TMP_EREG2) | SH_IMM(31), TMP_EREG2)); 410 return push_inst(compiler, SELECT_OP(DSUBU, SUBU) | SA(TMP_EREG1) | TA(TMP_EREG2) | DA(OVERFLOW_FLAG), OVERFLOW_FLAG); 411 412 case SLJIT_AND: 413 EMIT_LOGICAL(ANDI, AND); 414 return SLJIT_SUCCESS; 415 416 case SLJIT_OR: 417 EMIT_LOGICAL(ORI, OR); 418 return SLJIT_SUCCESS; 419 420 case SLJIT_XOR: 421 EMIT_LOGICAL(XORI, XOR); 422 return SLJIT_SUCCESS; 423 424 case SLJIT_SHL: 425 EMIT_SHIFT(DSLL, DSLL32, SLL, DSLLV, SLLV); 426 return SLJIT_SUCCESS; 427 428 case SLJIT_LSHR: 429 EMIT_SHIFT(DSRL, DSRL32, SRL, DSRLV, SRLV); 430 return SLJIT_SUCCESS; 431 432 case SLJIT_ASHR: 433 EMIT_SHIFT(DSRA, DSRA32, SRA, DSRAV, SRAV); 434 return SLJIT_SUCCESS; 435 } 436 437 SLJIT_ASSERT_STOP(); 438 return SLJIT_SUCCESS; 439 } 440 441 static SLJIT_INLINE sljit_si emit_const(struct sljit_compiler *compiler, sljit_si dst, sljit_sw init_value) 442 { 443 FAIL_IF(push_inst(compiler, LUI | T(dst) | IMM(init_value >> 48), DR(dst))); 444 FAIL_IF(push_inst(compiler, ORI | S(dst) | T(dst) | IMM(init_value >> 32), DR(dst))); 445 FAIL_IF(push_inst(compiler, DSLL | T(dst) | D(dst) | SH_IMM(16), DR(dst))); 446 FAIL_IF(push_inst(compiler, ORI | S(dst) | T(dst) | IMM(init_value >> 16), DR(dst))); 447 FAIL_IF(push_inst(compiler, DSLL | T(dst) | D(dst) | SH_IMM(16), DR(dst))); 448 return push_inst(compiler, ORI | S(dst) | T(dst) | IMM(init_value), DR(dst)); 449 } 450 451 SLJIT_API_FUNC_ATTRIBUTE void sljit_set_jump_addr(sljit_uw addr, sljit_uw new_addr) 452 { 453 sljit_ins *inst = (sljit_ins*)addr; 454 455 inst[0] = (inst[0] & 0xffff0000) | ((new_addr >> 48) & 0xffff); 456 inst[1] = (inst[1] & 0xffff0000) | ((new_addr >> 32) & 0xffff); 457 inst[3] = (inst[3] & 0xffff0000) | ((new_addr >> 16) & 0xffff); 458 inst[5] = (inst[5] & 0xffff0000) | (new_addr & 0xffff); 459 SLJIT_CACHE_FLUSH(inst, inst + 6); 460 } 461 462 SLJIT_API_FUNC_ATTRIBUTE void sljit_set_const(sljit_uw addr, sljit_sw new_constant) 463 { 464 sljit_ins *inst = (sljit_ins*)addr; 465 466 inst[0] = (inst[0] & 0xffff0000) | ((new_constant >> 48) & 0xffff); 467 inst[1] = (inst[1] & 0xffff0000) | ((new_constant >> 32) & 0xffff); 468 inst[3] = (inst[3] & 0xffff0000) | ((new_constant >> 16) & 0xffff); 469 inst[5] = (inst[5] & 0xffff0000) | (new_constant & 0xffff); 470 SLJIT_CACHE_FLUSH(inst, inst + 6); 471 } 472