1 1.4 alnsn /* $NetBSD: sljitNativePPC_64.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 /* ppc 64-bit arch dependent functions. */ 30 1.1 alnsn 31 1.1 alnsn #if defined(__GNUC__) || (defined(__IBM_GCC_ASM) && __IBM_GCC_ASM) 32 1.1 alnsn #define ASM_SLJIT_CLZ(src, dst) \ 33 1.1 alnsn __asm__ volatile ( "cntlzd %0, %1" : "=r"(dst) : "r"(src) ) 34 1.1 alnsn #elif defined(__xlc__) 35 1.1 alnsn #error "Please enable GCC syntax for inline assembly statements" 36 1.1 alnsn #else 37 1.1 alnsn #error "Must implement count leading zeroes" 38 1.1 alnsn #endif 39 1.1 alnsn 40 1.1 alnsn #define RLDI(dst, src, sh, mb, type) \ 41 1.1 alnsn (HI(30) | S(src) | A(dst) | ((type) << 2) | (((sh) & 0x1f) << 11) | (((sh) & 0x20) >> 4) | (((mb) & 0x1f) << 6) | ((mb) & 0x20)) 42 1.1 alnsn 43 1.1 alnsn #define PUSH_RLDICR(reg, shift) \ 44 1.1 alnsn push_inst(compiler, RLDI(reg, reg, 63 - shift, shift, 1)) 45 1.1 alnsn 46 1.3 alnsn static sljit_s32 load_immediate(struct sljit_compiler *compiler, sljit_s32 reg, sljit_sw imm) 47 1.1 alnsn { 48 1.1 alnsn sljit_uw tmp; 49 1.1 alnsn sljit_uw shift; 50 1.1 alnsn sljit_uw tmp2; 51 1.1 alnsn sljit_uw shift2; 52 1.1 alnsn 53 1.1 alnsn if (imm <= SIMM_MAX && imm >= SIMM_MIN) 54 1.1 alnsn return push_inst(compiler, ADDI | D(reg) | A(0) | IMM(imm)); 55 1.1 alnsn 56 1.1 alnsn if (!(imm & ~0xffff)) 57 1.2 alnsn return push_inst(compiler, ORI | S(TMP_ZERO) | A(reg) | IMM(imm)); 58 1.1 alnsn 59 1.2 alnsn if (imm <= 0x7fffffffl && imm >= -0x80000000l) { 60 1.1 alnsn FAIL_IF(push_inst(compiler, ADDIS | D(reg) | A(0) | IMM(imm >> 16))); 61 1.1 alnsn return (imm & 0xffff) ? push_inst(compiler, ORI | S(reg) | A(reg) | IMM(imm)) : SLJIT_SUCCESS; 62 1.1 alnsn } 63 1.1 alnsn 64 1.1 alnsn /* Count leading zeroes. */ 65 1.1 alnsn tmp = (imm >= 0) ? imm : ~imm; 66 1.1 alnsn ASM_SLJIT_CLZ(tmp, shift); 67 1.1 alnsn SLJIT_ASSERT(shift > 0); 68 1.1 alnsn shift--; 69 1.1 alnsn tmp = (imm << shift); 70 1.1 alnsn 71 1.1 alnsn if ((tmp & ~0xffff000000000000ul) == 0) { 72 1.1 alnsn FAIL_IF(push_inst(compiler, ADDI | D(reg) | A(0) | IMM(tmp >> 48))); 73 1.1 alnsn shift += 15; 74 1.1 alnsn return PUSH_RLDICR(reg, shift); 75 1.1 alnsn } 76 1.1 alnsn 77 1.1 alnsn if ((tmp & ~0xffffffff00000000ul) == 0) { 78 1.1 alnsn FAIL_IF(push_inst(compiler, ADDIS | D(reg) | A(0) | IMM(tmp >> 48))); 79 1.1 alnsn FAIL_IF(push_inst(compiler, ORI | S(reg) | A(reg) | IMM(tmp >> 32))); 80 1.1 alnsn shift += 31; 81 1.1 alnsn return PUSH_RLDICR(reg, shift); 82 1.1 alnsn } 83 1.1 alnsn 84 1.1 alnsn /* Cut out the 16 bit from immediate. */ 85 1.1 alnsn shift += 15; 86 1.1 alnsn tmp2 = imm & ((1ul << (63 - shift)) - 1); 87 1.1 alnsn 88 1.1 alnsn if (tmp2 <= 0xffff) { 89 1.1 alnsn FAIL_IF(push_inst(compiler, ADDI | D(reg) | A(0) | IMM(tmp >> 48))); 90 1.1 alnsn FAIL_IF(PUSH_RLDICR(reg, shift)); 91 1.1 alnsn return push_inst(compiler, ORI | S(reg) | A(reg) | tmp2); 92 1.1 alnsn } 93 1.1 alnsn 94 1.1 alnsn if (tmp2 <= 0xffffffff) { 95 1.1 alnsn FAIL_IF(push_inst(compiler, ADDI | D(reg) | A(0) | IMM(tmp >> 48))); 96 1.1 alnsn FAIL_IF(PUSH_RLDICR(reg, shift)); 97 1.1 alnsn FAIL_IF(push_inst(compiler, ORIS | S(reg) | A(reg) | (tmp2 >> 16))); 98 1.1 alnsn return (imm & 0xffff) ? push_inst(compiler, ORI | S(reg) | A(reg) | IMM(tmp2)) : SLJIT_SUCCESS; 99 1.1 alnsn } 100 1.1 alnsn 101 1.1 alnsn ASM_SLJIT_CLZ(tmp2, shift2); 102 1.1 alnsn tmp2 <<= shift2; 103 1.1 alnsn 104 1.1 alnsn if ((tmp2 & ~0xffff000000000000ul) == 0) { 105 1.1 alnsn FAIL_IF(push_inst(compiler, ADDI | D(reg) | A(0) | IMM(tmp >> 48))); 106 1.1 alnsn shift2 += 15; 107 1.1 alnsn shift += (63 - shift2); 108 1.1 alnsn FAIL_IF(PUSH_RLDICR(reg, shift)); 109 1.1 alnsn FAIL_IF(push_inst(compiler, ORI | S(reg) | A(reg) | (tmp2 >> 48))); 110 1.1 alnsn return PUSH_RLDICR(reg, shift2); 111 1.1 alnsn } 112 1.1 alnsn 113 1.1 alnsn /* The general version. */ 114 1.1 alnsn FAIL_IF(push_inst(compiler, ADDIS | D(reg) | A(0) | IMM(imm >> 48))); 115 1.1 alnsn FAIL_IF(push_inst(compiler, ORI | S(reg) | A(reg) | IMM(imm >> 32))); 116 1.1 alnsn FAIL_IF(PUSH_RLDICR(reg, 31)); 117 1.1 alnsn FAIL_IF(push_inst(compiler, ORIS | S(reg) | A(reg) | IMM(imm >> 16))); 118 1.1 alnsn return push_inst(compiler, ORI | S(reg) | A(reg) | IMM(imm)); 119 1.1 alnsn } 120 1.1 alnsn 121 1.1 alnsn /* Simplified mnemonics: clrldi. */ 122 1.1 alnsn #define INS_CLEAR_LEFT(dst, src, from) \ 123 1.1 alnsn (RLDICL | S(src) | A(dst) | ((from) << 6) | (1 << 5)) 124 1.1 alnsn 125 1.1 alnsn /* Sign extension for integer operations. */ 126 1.1 alnsn #define UN_EXTS() \ 127 1.1 alnsn if ((flags & (ALT_SIGN_EXT | REG2_SOURCE)) == (ALT_SIGN_EXT | REG2_SOURCE)) { \ 128 1.1 alnsn FAIL_IF(push_inst(compiler, EXTSW | S(src2) | A(TMP_REG2))); \ 129 1.1 alnsn src2 = TMP_REG2; \ 130 1.1 alnsn } 131 1.1 alnsn 132 1.1 alnsn #define BIN_EXTS() \ 133 1.1 alnsn if (flags & ALT_SIGN_EXT) { \ 134 1.1 alnsn if (flags & REG1_SOURCE) { \ 135 1.1 alnsn FAIL_IF(push_inst(compiler, EXTSW | S(src1) | A(TMP_REG1))); \ 136 1.1 alnsn src1 = TMP_REG1; \ 137 1.1 alnsn } \ 138 1.1 alnsn if (flags & REG2_SOURCE) { \ 139 1.1 alnsn FAIL_IF(push_inst(compiler, EXTSW | S(src2) | A(TMP_REG2))); \ 140 1.1 alnsn src2 = TMP_REG2; \ 141 1.1 alnsn } \ 142 1.1 alnsn } 143 1.1 alnsn 144 1.1 alnsn #define BIN_IMM_EXTS() \ 145 1.1 alnsn if ((flags & (ALT_SIGN_EXT | REG1_SOURCE)) == (ALT_SIGN_EXT | REG1_SOURCE)) { \ 146 1.1 alnsn FAIL_IF(push_inst(compiler, EXTSW | S(src1) | A(TMP_REG1))); \ 147 1.1 alnsn src1 = TMP_REG1; \ 148 1.1 alnsn } 149 1.1 alnsn 150 1.3 alnsn static SLJIT_INLINE sljit_s32 emit_single_op(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 flags, 151 1.3 alnsn sljit_s32 dst, sljit_s32 src1, sljit_s32 src2) 152 1.1 alnsn { 153 1.1 alnsn switch (op) { 154 1.2 alnsn case SLJIT_MOV: 155 1.2 alnsn case SLJIT_MOV_P: 156 1.2 alnsn SLJIT_ASSERT(src1 == TMP_REG1); 157 1.2 alnsn if (dst != src2) 158 1.2 alnsn return push_inst(compiler, OR | S(src2) | A(dst) | B(src2)); 159 1.2 alnsn return SLJIT_SUCCESS; 160 1.2 alnsn 161 1.3 alnsn case SLJIT_MOV_U32: 162 1.3 alnsn case SLJIT_MOV_S32: 163 1.2 alnsn SLJIT_ASSERT(src1 == TMP_REG1); 164 1.2 alnsn if ((flags & (REG_DEST | REG2_SOURCE)) == (REG_DEST | REG2_SOURCE)) { 165 1.3 alnsn if (op == SLJIT_MOV_S32) 166 1.2 alnsn return push_inst(compiler, EXTSW | S(src2) | A(dst)); 167 1.2 alnsn return push_inst(compiler, INS_CLEAR_LEFT(dst, src2, 0)); 168 1.2 alnsn } 169 1.2 alnsn else { 170 1.2 alnsn SLJIT_ASSERT(dst == src2); 171 1.2 alnsn } 172 1.2 alnsn return SLJIT_SUCCESS; 173 1.2 alnsn 174 1.3 alnsn case SLJIT_MOV_U8: 175 1.3 alnsn case SLJIT_MOV_S8: 176 1.2 alnsn SLJIT_ASSERT(src1 == TMP_REG1); 177 1.2 alnsn if ((flags & (REG_DEST | REG2_SOURCE)) == (REG_DEST | REG2_SOURCE)) { 178 1.3 alnsn if (op == SLJIT_MOV_S8) 179 1.2 alnsn return push_inst(compiler, EXTSB | S(src2) | A(dst)); 180 1.2 alnsn return push_inst(compiler, INS_CLEAR_LEFT(dst, src2, 24)); 181 1.2 alnsn } 182 1.3 alnsn else if ((flags & REG_DEST) && op == SLJIT_MOV_S8) 183 1.2 alnsn return push_inst(compiler, EXTSB | S(src2) | A(dst)); 184 1.2 alnsn else { 185 1.2 alnsn SLJIT_ASSERT(dst == src2); 186 1.2 alnsn } 187 1.2 alnsn return SLJIT_SUCCESS; 188 1.2 alnsn 189 1.3 alnsn case SLJIT_MOV_U16: 190 1.3 alnsn case SLJIT_MOV_S16: 191 1.2 alnsn SLJIT_ASSERT(src1 == TMP_REG1); 192 1.2 alnsn if ((flags & (REG_DEST | REG2_SOURCE)) == (REG_DEST | REG2_SOURCE)) { 193 1.3 alnsn if (op == SLJIT_MOV_S16) 194 1.2 alnsn return push_inst(compiler, EXTSH | S(src2) | A(dst)); 195 1.2 alnsn return push_inst(compiler, INS_CLEAR_LEFT(dst, src2, 16)); 196 1.2 alnsn } 197 1.2 alnsn else { 198 1.2 alnsn SLJIT_ASSERT(dst == src2); 199 1.2 alnsn } 200 1.2 alnsn return SLJIT_SUCCESS; 201 1.2 alnsn 202 1.2 alnsn case SLJIT_NOT: 203 1.2 alnsn SLJIT_ASSERT(src1 == TMP_REG1); 204 1.2 alnsn UN_EXTS(); 205 1.2 alnsn return push_inst(compiler, NOR | RC(flags) | S(src2) | A(dst) | B(src2)); 206 1.2 alnsn 207 1.2 alnsn case SLJIT_NEG: 208 1.2 alnsn SLJIT_ASSERT(src1 == TMP_REG1); 209 1.2 alnsn UN_EXTS(); 210 1.2 alnsn return push_inst(compiler, NEG | OERC(flags) | D(dst) | A(src2)); 211 1.2 alnsn 212 1.2 alnsn case SLJIT_CLZ: 213 1.2 alnsn SLJIT_ASSERT(src1 == TMP_REG1); 214 1.2 alnsn if (flags & ALT_FORM1) 215 1.2 alnsn return push_inst(compiler, CNTLZW | RC(flags) | S(src2) | A(dst)); 216 1.2 alnsn return push_inst(compiler, CNTLZD | RC(flags) | S(src2) | A(dst)); 217 1.2 alnsn 218 1.1 alnsn case SLJIT_ADD: 219 1.1 alnsn if (flags & ALT_FORM1) { 220 1.1 alnsn /* Flags does not set: BIN_IMM_EXTS unnecessary. */ 221 1.1 alnsn SLJIT_ASSERT(src2 == TMP_REG2); 222 1.1 alnsn return push_inst(compiler, ADDI | D(dst) | A(src1) | compiler->imm); 223 1.1 alnsn } 224 1.1 alnsn if (flags & ALT_FORM2) { 225 1.1 alnsn /* Flags does not set: BIN_IMM_EXTS unnecessary. */ 226 1.1 alnsn SLJIT_ASSERT(src2 == TMP_REG2); 227 1.1 alnsn return push_inst(compiler, ADDIS | D(dst) | A(src1) | compiler->imm); 228 1.1 alnsn } 229 1.1 alnsn if (flags & ALT_FORM3) { 230 1.1 alnsn SLJIT_ASSERT(src2 == TMP_REG2); 231 1.1 alnsn BIN_IMM_EXTS(); 232 1.1 alnsn return push_inst(compiler, ADDIC | D(dst) | A(src1) | compiler->imm); 233 1.1 alnsn } 234 1.1 alnsn if (flags & ALT_FORM4) { 235 1.1 alnsn /* Flags does not set: BIN_IMM_EXTS unnecessary. */ 236 1.1 alnsn FAIL_IF(push_inst(compiler, ADDI | D(dst) | A(src1) | (compiler->imm & 0xffff))); 237 1.1 alnsn return push_inst(compiler, ADDIS | D(dst) | A(dst) | (((compiler->imm >> 16) & 0xffff) + ((compiler->imm >> 15) & 0x1))); 238 1.1 alnsn } 239 1.1 alnsn if (!(flags & ALT_SET_FLAGS)) 240 1.1 alnsn return push_inst(compiler, ADD | D(dst) | A(src1) | B(src2)); 241 1.1 alnsn BIN_EXTS(); 242 1.1 alnsn return push_inst(compiler, ADDC | OERC(ALT_SET_FLAGS) | D(dst) | A(src1) | B(src2)); 243 1.1 alnsn 244 1.1 alnsn case SLJIT_ADDC: 245 1.1 alnsn BIN_EXTS(); 246 1.1 alnsn return push_inst(compiler, ADDE | D(dst) | A(src1) | B(src2)); 247 1.1 alnsn 248 1.1 alnsn case SLJIT_SUB: 249 1.1 alnsn if (flags & ALT_FORM1) { 250 1.1 alnsn /* Flags does not set: BIN_IMM_EXTS unnecessary. */ 251 1.1 alnsn SLJIT_ASSERT(src2 == TMP_REG2); 252 1.1 alnsn return push_inst(compiler, SUBFIC | D(dst) | A(src1) | compiler->imm); 253 1.1 alnsn } 254 1.1 alnsn if (flags & (ALT_FORM2 | ALT_FORM3)) { 255 1.1 alnsn SLJIT_ASSERT(src2 == TMP_REG2); 256 1.4 alnsn return push_inst(compiler, ((flags & ALT_FORM2) ? CMPI : CMPLI) | CRD(0 | ((flags & ALT_SIGN_EXT) ? 0 : 1)) | A(src1) | compiler->imm); 257 1.1 alnsn } 258 1.1 alnsn if (flags & (ALT_FORM4 | ALT_FORM5)) { 259 1.4 alnsn return push_inst(compiler, ((flags & ALT_FORM4) ? CMP : CMPL) | CRD(0 | ((flags & ALT_SIGN_EXT) ? 0 : 1)) | A(src1) | B(src2)); 260 1.4 alnsn } 261 1.4 alnsn if (flags & ALT_FORM6) { 262 1.4 alnsn SLJIT_ASSERT(src2 == TMP_REG2); 263 1.4 alnsn FAIL_IF(push_inst(compiler, CMPLI | CRD(0 | ((flags & ALT_SIGN_EXT) ? 0 : 1)) | A(src1) | compiler->imm)); 264 1.4 alnsn return push_inst(compiler, ADDI | D(dst) | A(src1) | (-compiler->imm & 0xffff)); 265 1.4 alnsn } 266 1.4 alnsn if (flags & ALT_FORM7) { 267 1.4 alnsn FAIL_IF(push_inst(compiler, CMPL | CRD(0 | ((flags & ALT_SIGN_EXT) ? 0 : 1)) | A(src1) | B(src2))); 268 1.4 alnsn return push_inst(compiler, SUBF | D(dst) | A(src2) | B(src1)); 269 1.1 alnsn } 270 1.1 alnsn if (!(flags & ALT_SET_FLAGS)) 271 1.1 alnsn return push_inst(compiler, SUBF | D(dst) | A(src2) | B(src1)); 272 1.1 alnsn BIN_EXTS(); 273 1.1 alnsn return push_inst(compiler, SUBFC | OERC(ALT_SET_FLAGS) | D(dst) | A(src2) | B(src1)); 274 1.1 alnsn 275 1.1 alnsn case SLJIT_SUBC: 276 1.1 alnsn BIN_EXTS(); 277 1.1 alnsn return push_inst(compiler, SUBFE | D(dst) | A(src2) | B(src1)); 278 1.1 alnsn 279 1.1 alnsn case SLJIT_MUL: 280 1.1 alnsn if (flags & ALT_FORM1) { 281 1.1 alnsn SLJIT_ASSERT(src2 == TMP_REG2); 282 1.1 alnsn return push_inst(compiler, MULLI | D(dst) | A(src1) | compiler->imm); 283 1.1 alnsn } 284 1.1 alnsn BIN_EXTS(); 285 1.1 alnsn if (flags & ALT_FORM2) 286 1.1 alnsn return push_inst(compiler, MULLW | OERC(flags) | D(dst) | A(src2) | B(src1)); 287 1.1 alnsn return push_inst(compiler, MULLD | OERC(flags) | D(dst) | A(src2) | B(src1)); 288 1.1 alnsn 289 1.1 alnsn case SLJIT_AND: 290 1.1 alnsn if (flags & ALT_FORM1) { 291 1.1 alnsn SLJIT_ASSERT(src2 == TMP_REG2); 292 1.1 alnsn return push_inst(compiler, ANDI | S(src1) | A(dst) | compiler->imm); 293 1.1 alnsn } 294 1.1 alnsn if (flags & ALT_FORM2) { 295 1.1 alnsn SLJIT_ASSERT(src2 == TMP_REG2); 296 1.1 alnsn return push_inst(compiler, ANDIS | S(src1) | A(dst) | compiler->imm); 297 1.1 alnsn } 298 1.1 alnsn return push_inst(compiler, AND | RC(flags) | S(src1) | A(dst) | B(src2)); 299 1.1 alnsn 300 1.1 alnsn case SLJIT_OR: 301 1.1 alnsn if (flags & ALT_FORM1) { 302 1.1 alnsn SLJIT_ASSERT(src2 == TMP_REG2); 303 1.1 alnsn return push_inst(compiler, ORI | S(src1) | A(dst) | compiler->imm); 304 1.1 alnsn } 305 1.1 alnsn if (flags & ALT_FORM2) { 306 1.1 alnsn SLJIT_ASSERT(src2 == TMP_REG2); 307 1.1 alnsn return push_inst(compiler, ORIS | S(src1) | A(dst) | compiler->imm); 308 1.1 alnsn } 309 1.1 alnsn if (flags & ALT_FORM3) { 310 1.1 alnsn SLJIT_ASSERT(src2 == TMP_REG2); 311 1.1 alnsn FAIL_IF(push_inst(compiler, ORI | S(src1) | A(dst) | IMM(compiler->imm))); 312 1.1 alnsn return push_inst(compiler, ORIS | S(dst) | A(dst) | IMM(compiler->imm >> 16)); 313 1.1 alnsn } 314 1.1 alnsn return push_inst(compiler, OR | RC(flags) | S(src1) | A(dst) | B(src2)); 315 1.1 alnsn 316 1.1 alnsn case SLJIT_XOR: 317 1.1 alnsn if (flags & ALT_FORM1) { 318 1.1 alnsn SLJIT_ASSERT(src2 == TMP_REG2); 319 1.1 alnsn return push_inst(compiler, XORI | S(src1) | A(dst) | compiler->imm); 320 1.1 alnsn } 321 1.1 alnsn if (flags & ALT_FORM2) { 322 1.1 alnsn SLJIT_ASSERT(src2 == TMP_REG2); 323 1.1 alnsn return push_inst(compiler, XORIS | S(src1) | A(dst) | compiler->imm); 324 1.1 alnsn } 325 1.1 alnsn if (flags & ALT_FORM3) { 326 1.1 alnsn SLJIT_ASSERT(src2 == TMP_REG2); 327 1.1 alnsn FAIL_IF(push_inst(compiler, XORI | S(src1) | A(dst) | IMM(compiler->imm))); 328 1.1 alnsn return push_inst(compiler, XORIS | S(dst) | A(dst) | IMM(compiler->imm >> 16)); 329 1.1 alnsn } 330 1.1 alnsn return push_inst(compiler, XOR | RC(flags) | S(src1) | A(dst) | B(src2)); 331 1.1 alnsn 332 1.1 alnsn case SLJIT_SHL: 333 1.1 alnsn if (flags & ALT_FORM1) { 334 1.1 alnsn SLJIT_ASSERT(src2 == TMP_REG2); 335 1.1 alnsn if (flags & ALT_FORM2) { 336 1.1 alnsn compiler->imm &= 0x1f; 337 1.1 alnsn return push_inst(compiler, RLWINM | RC(flags) | S(src1) | A(dst) | (compiler->imm << 11) | ((31 - compiler->imm) << 1)); 338 1.1 alnsn } 339 1.4 alnsn compiler->imm &= 0x3f; 340 1.4 alnsn return push_inst(compiler, RLDI(dst, src1, compiler->imm, 63 - compiler->imm, 1) | RC(flags)); 341 1.1 alnsn } 342 1.2 alnsn return push_inst(compiler, ((flags & ALT_FORM2) ? SLW : SLD) | RC(flags) | S(src1) | A(dst) | B(src2)); 343 1.1 alnsn 344 1.1 alnsn case SLJIT_LSHR: 345 1.1 alnsn if (flags & ALT_FORM1) { 346 1.1 alnsn SLJIT_ASSERT(src2 == TMP_REG2); 347 1.1 alnsn if (flags & ALT_FORM2) { 348 1.1 alnsn compiler->imm &= 0x1f; 349 1.1 alnsn return push_inst(compiler, RLWINM | RC(flags) | S(src1) | A(dst) | (((32 - compiler->imm) & 0x1f) << 11) | (compiler->imm << 6) | (31 << 1)); 350 1.1 alnsn } 351 1.4 alnsn compiler->imm &= 0x3f; 352 1.4 alnsn return push_inst(compiler, RLDI(dst, src1, 64 - compiler->imm, compiler->imm, 0) | RC(flags)); 353 1.1 alnsn } 354 1.2 alnsn return push_inst(compiler, ((flags & ALT_FORM2) ? SRW : SRD) | RC(flags) | S(src1) | A(dst) | B(src2)); 355 1.1 alnsn 356 1.1 alnsn case SLJIT_ASHR: 357 1.1 alnsn if (flags & ALT_FORM1) { 358 1.1 alnsn SLJIT_ASSERT(src2 == TMP_REG2); 359 1.1 alnsn if (flags & ALT_FORM2) { 360 1.1 alnsn compiler->imm &= 0x1f; 361 1.4 alnsn return push_inst(compiler, SRAWI | RC(flags) | S(src1) | A(dst) | (compiler->imm << 11)); 362 1.1 alnsn } 363 1.4 alnsn compiler->imm &= 0x3f; 364 1.4 alnsn return push_inst(compiler, SRADI | RC(flags) | S(src1) | A(dst) | ((compiler->imm & 0x1f) << 11) | ((compiler->imm & 0x20) >> 4)); 365 1.1 alnsn } 366 1.4 alnsn return push_inst(compiler, ((flags & ALT_FORM2) ? SRAW : SRAD) | RC(flags) | S(src1) | A(dst) | B(src2)); 367 1.1 alnsn } 368 1.1 alnsn 369 1.4 alnsn SLJIT_UNREACHABLE(); 370 1.1 alnsn return SLJIT_SUCCESS; 371 1.1 alnsn } 372 1.1 alnsn 373 1.3 alnsn static SLJIT_INLINE sljit_s32 emit_const(struct sljit_compiler *compiler, sljit_s32 reg, sljit_sw init_value) 374 1.1 alnsn { 375 1.1 alnsn FAIL_IF(push_inst(compiler, ADDIS | D(reg) | A(0) | IMM(init_value >> 48))); 376 1.1 alnsn FAIL_IF(push_inst(compiler, ORI | S(reg) | A(reg) | IMM(init_value >> 32))); 377 1.1 alnsn FAIL_IF(PUSH_RLDICR(reg, 31)); 378 1.1 alnsn FAIL_IF(push_inst(compiler, ORIS | S(reg) | A(reg) | IMM(init_value >> 16))); 379 1.1 alnsn return push_inst(compiler, ORI | S(reg) | A(reg) | IMM(init_value)); 380 1.1 alnsn } 381 1.1 alnsn 382 1.4 alnsn SLJIT_API_FUNC_ATTRIBUTE void sljit_set_jump_addr(sljit_uw addr, sljit_uw new_target, sljit_sw executable_offset) 383 1.1 alnsn { 384 1.1 alnsn sljit_ins *inst = (sljit_ins*)addr; 385 1.1 alnsn 386 1.4 alnsn inst[0] = (inst[0] & 0xffff0000) | ((new_target >> 48) & 0xffff); 387 1.4 alnsn inst[1] = (inst[1] & 0xffff0000) | ((new_target >> 32) & 0xffff); 388 1.4 alnsn inst[3] = (inst[3] & 0xffff0000) | ((new_target >> 16) & 0xffff); 389 1.4 alnsn inst[4] = (inst[4] & 0xffff0000) | (new_target & 0xffff); 390 1.4 alnsn inst = (sljit_ins *)SLJIT_ADD_EXEC_OFFSET(inst, executable_offset); 391 1.1 alnsn SLJIT_CACHE_FLUSH(inst, inst + 5); 392 1.1 alnsn } 393 1.1 alnsn 394 1.4 alnsn SLJIT_API_FUNC_ATTRIBUTE void sljit_set_const(sljit_uw addr, sljit_sw new_constant, sljit_sw executable_offset) 395 1.1 alnsn { 396 1.1 alnsn sljit_ins *inst = (sljit_ins*)addr; 397 1.1 alnsn 398 1.1 alnsn inst[0] = (inst[0] & 0xffff0000) | ((new_constant >> 48) & 0xffff); 399 1.1 alnsn inst[1] = (inst[1] & 0xffff0000) | ((new_constant >> 32) & 0xffff); 400 1.1 alnsn inst[3] = (inst[3] & 0xffff0000) | ((new_constant >> 16) & 0xffff); 401 1.1 alnsn inst[4] = (inst[4] & 0xffff0000) | (new_constant & 0xffff); 402 1.4 alnsn inst = (sljit_ins *)SLJIT_ADD_EXEC_OFFSET(inst, executable_offset); 403 1.1 alnsn SLJIT_CACHE_FLUSH(inst, inst + 5); 404 1.1 alnsn } 405