1 1.4 alnsn /* $NetBSD: sljitNativePPC_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 /* ppc 32-bit arch dependent functions. */ 30 1.1 alnsn 31 1.3 alnsn static sljit_s32 load_immediate(struct sljit_compiler *compiler, sljit_s32 reg, sljit_sw imm) 32 1.1 alnsn { 33 1.1 alnsn if (imm <= SIMM_MAX && imm >= SIMM_MIN) 34 1.1 alnsn return push_inst(compiler, ADDI | D(reg) | A(0) | IMM(imm)); 35 1.1 alnsn 36 1.1 alnsn if (!(imm & ~0xffff)) 37 1.2 alnsn return push_inst(compiler, ORI | S(TMP_ZERO) | A(reg) | IMM(imm)); 38 1.1 alnsn 39 1.1 alnsn FAIL_IF(push_inst(compiler, ADDIS | D(reg) | A(0) | IMM(imm >> 16))); 40 1.1 alnsn return (imm & 0xffff) ? push_inst(compiler, ORI | S(reg) | A(reg) | IMM(imm)) : SLJIT_SUCCESS; 41 1.1 alnsn } 42 1.1 alnsn 43 1.1 alnsn #define INS_CLEAR_LEFT(dst, src, from) \ 44 1.1 alnsn (RLWINM | S(src) | A(dst) | ((from) << 6) | (31 << 1)) 45 1.1 alnsn 46 1.3 alnsn static SLJIT_INLINE sljit_s32 emit_single_op(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 flags, 47 1.3 alnsn sljit_s32 dst, sljit_s32 src1, sljit_s32 src2) 48 1.1 alnsn { 49 1.1 alnsn switch (op) { 50 1.2 alnsn case SLJIT_MOV: 51 1.3 alnsn case SLJIT_MOV_U32: 52 1.3 alnsn case SLJIT_MOV_S32: 53 1.2 alnsn case SLJIT_MOV_P: 54 1.2 alnsn SLJIT_ASSERT(src1 == TMP_REG1); 55 1.2 alnsn if (dst != src2) 56 1.2 alnsn return push_inst(compiler, OR | S(src2) | A(dst) | B(src2)); 57 1.2 alnsn return SLJIT_SUCCESS; 58 1.2 alnsn 59 1.3 alnsn case SLJIT_MOV_U8: 60 1.3 alnsn case SLJIT_MOV_S8: 61 1.2 alnsn SLJIT_ASSERT(src1 == TMP_REG1); 62 1.2 alnsn if ((flags & (REG_DEST | REG2_SOURCE)) == (REG_DEST | REG2_SOURCE)) { 63 1.3 alnsn if (op == SLJIT_MOV_S8) 64 1.2 alnsn return push_inst(compiler, EXTSB | S(src2) | A(dst)); 65 1.2 alnsn return push_inst(compiler, INS_CLEAR_LEFT(dst, src2, 24)); 66 1.2 alnsn } 67 1.3 alnsn else if ((flags & REG_DEST) && op == SLJIT_MOV_S8) 68 1.2 alnsn return push_inst(compiler, EXTSB | S(src2) | A(dst)); 69 1.2 alnsn else { 70 1.2 alnsn SLJIT_ASSERT(dst == src2); 71 1.2 alnsn } 72 1.2 alnsn return SLJIT_SUCCESS; 73 1.2 alnsn 74 1.3 alnsn case SLJIT_MOV_U16: 75 1.3 alnsn case SLJIT_MOV_S16: 76 1.2 alnsn SLJIT_ASSERT(src1 == TMP_REG1); 77 1.2 alnsn if ((flags & (REG_DEST | REG2_SOURCE)) == (REG_DEST | REG2_SOURCE)) { 78 1.3 alnsn if (op == SLJIT_MOV_S16) 79 1.2 alnsn return push_inst(compiler, EXTSH | S(src2) | A(dst)); 80 1.2 alnsn return push_inst(compiler, INS_CLEAR_LEFT(dst, src2, 16)); 81 1.2 alnsn } 82 1.2 alnsn else { 83 1.2 alnsn SLJIT_ASSERT(dst == src2); 84 1.2 alnsn } 85 1.2 alnsn return SLJIT_SUCCESS; 86 1.2 alnsn 87 1.2 alnsn case SLJIT_NOT: 88 1.2 alnsn SLJIT_ASSERT(src1 == TMP_REG1); 89 1.2 alnsn return push_inst(compiler, NOR | RC(flags) | S(src2) | A(dst) | B(src2)); 90 1.2 alnsn 91 1.2 alnsn case SLJIT_NEG: 92 1.2 alnsn SLJIT_ASSERT(src1 == TMP_REG1); 93 1.2 alnsn return push_inst(compiler, NEG | OERC(flags) | D(dst) | A(src2)); 94 1.2 alnsn 95 1.2 alnsn case SLJIT_CLZ: 96 1.2 alnsn SLJIT_ASSERT(src1 == TMP_REG1); 97 1.2 alnsn return push_inst(compiler, CNTLZW | RC(flags) | S(src2) | A(dst)); 98 1.2 alnsn 99 1.1 alnsn case SLJIT_ADD: 100 1.1 alnsn if (flags & ALT_FORM1) { 101 1.1 alnsn /* Flags does not set: BIN_IMM_EXTS unnecessary. */ 102 1.1 alnsn SLJIT_ASSERT(src2 == TMP_REG2); 103 1.1 alnsn return push_inst(compiler, ADDI | D(dst) | A(src1) | compiler->imm); 104 1.1 alnsn } 105 1.1 alnsn if (flags & ALT_FORM2) { 106 1.1 alnsn /* Flags does not set: BIN_IMM_EXTS unnecessary. */ 107 1.1 alnsn SLJIT_ASSERT(src2 == TMP_REG2); 108 1.1 alnsn return push_inst(compiler, ADDIS | D(dst) | A(src1) | compiler->imm); 109 1.1 alnsn } 110 1.1 alnsn if (flags & ALT_FORM3) { 111 1.1 alnsn SLJIT_ASSERT(src2 == TMP_REG2); 112 1.1 alnsn return push_inst(compiler, ADDIC | D(dst) | A(src1) | compiler->imm); 113 1.1 alnsn } 114 1.1 alnsn if (flags & ALT_FORM4) { 115 1.1 alnsn /* Flags does not set: BIN_IMM_EXTS unnecessary. */ 116 1.1 alnsn FAIL_IF(push_inst(compiler, ADDI | D(dst) | A(src1) | (compiler->imm & 0xffff))); 117 1.1 alnsn return push_inst(compiler, ADDIS | D(dst) | A(dst) | (((compiler->imm >> 16) & 0xffff) + ((compiler->imm >> 15) & 0x1))); 118 1.1 alnsn } 119 1.1 alnsn if (!(flags & ALT_SET_FLAGS)) 120 1.1 alnsn return push_inst(compiler, ADD | D(dst) | A(src1) | B(src2)); 121 1.1 alnsn return push_inst(compiler, ADDC | OERC(ALT_SET_FLAGS) | D(dst) | A(src1) | B(src2)); 122 1.1 alnsn 123 1.1 alnsn case SLJIT_ADDC: 124 1.1 alnsn return push_inst(compiler, ADDE | D(dst) | A(src1) | B(src2)); 125 1.1 alnsn 126 1.1 alnsn case SLJIT_SUB: 127 1.1 alnsn if (flags & ALT_FORM1) { 128 1.1 alnsn SLJIT_ASSERT(src2 == TMP_REG2); 129 1.1 alnsn return push_inst(compiler, SUBFIC | D(dst) | A(src1) | compiler->imm); 130 1.1 alnsn } 131 1.1 alnsn if (flags & (ALT_FORM2 | ALT_FORM3)) { 132 1.1 alnsn SLJIT_ASSERT(src2 == TMP_REG2); 133 1.4 alnsn return push_inst(compiler, ((flags & ALT_FORM2) ? CMPI : CMPLI) | CRD(0) | A(src1) | compiler->imm); 134 1.1 alnsn } 135 1.1 alnsn if (flags & (ALT_FORM4 | ALT_FORM5)) { 136 1.4 alnsn return push_inst(compiler, ((flags & ALT_FORM4) ? CMP : CMPL) | CRD(0) | A(src1) | B(src2)); 137 1.4 alnsn } 138 1.4 alnsn if (flags & ALT_FORM6) { 139 1.4 alnsn SLJIT_ASSERT(src2 == TMP_REG2); 140 1.4 alnsn FAIL_IF(push_inst(compiler, CMPLI | CRD(0) | A(src1) | compiler->imm)); 141 1.4 alnsn return push_inst(compiler, ADDI | D(dst) | A(src1) | (-compiler->imm & 0xffff)); 142 1.4 alnsn } 143 1.4 alnsn if (flags & ALT_FORM7) { 144 1.4 alnsn FAIL_IF(push_inst(compiler, CMPL | CRD(0) | A(src1) | B(src2))); 145 1.4 alnsn return push_inst(compiler, SUBF | D(dst) | A(src2) | B(src1)); 146 1.1 alnsn } 147 1.1 alnsn if (!(flags & ALT_SET_FLAGS)) 148 1.1 alnsn return push_inst(compiler, SUBF | D(dst) | A(src2) | B(src1)); 149 1.1 alnsn return push_inst(compiler, SUBFC | OERC(ALT_SET_FLAGS) | D(dst) | A(src2) | B(src1)); 150 1.1 alnsn 151 1.1 alnsn case SLJIT_SUBC: 152 1.1 alnsn return push_inst(compiler, SUBFE | D(dst) | A(src2) | B(src1)); 153 1.1 alnsn 154 1.1 alnsn case SLJIT_MUL: 155 1.1 alnsn if (flags & ALT_FORM1) { 156 1.1 alnsn SLJIT_ASSERT(src2 == TMP_REG2); 157 1.1 alnsn return push_inst(compiler, MULLI | D(dst) | A(src1) | compiler->imm); 158 1.1 alnsn } 159 1.1 alnsn return push_inst(compiler, MULLW | OERC(flags) | D(dst) | A(src2) | B(src1)); 160 1.1 alnsn 161 1.1 alnsn case SLJIT_AND: 162 1.1 alnsn if (flags & ALT_FORM1) { 163 1.1 alnsn SLJIT_ASSERT(src2 == TMP_REG2); 164 1.1 alnsn return push_inst(compiler, ANDI | S(src1) | A(dst) | compiler->imm); 165 1.1 alnsn } 166 1.1 alnsn if (flags & ALT_FORM2) { 167 1.1 alnsn SLJIT_ASSERT(src2 == TMP_REG2); 168 1.1 alnsn return push_inst(compiler, ANDIS | S(src1) | A(dst) | compiler->imm); 169 1.1 alnsn } 170 1.1 alnsn return push_inst(compiler, AND | RC(flags) | S(src1) | A(dst) | B(src2)); 171 1.1 alnsn 172 1.1 alnsn case SLJIT_OR: 173 1.1 alnsn if (flags & ALT_FORM1) { 174 1.1 alnsn SLJIT_ASSERT(src2 == TMP_REG2); 175 1.1 alnsn return push_inst(compiler, ORI | S(src1) | A(dst) | compiler->imm); 176 1.1 alnsn } 177 1.1 alnsn if (flags & ALT_FORM2) { 178 1.1 alnsn SLJIT_ASSERT(src2 == TMP_REG2); 179 1.1 alnsn return push_inst(compiler, ORIS | S(src1) | A(dst) | compiler->imm); 180 1.1 alnsn } 181 1.1 alnsn if (flags & ALT_FORM3) { 182 1.1 alnsn SLJIT_ASSERT(src2 == TMP_REG2); 183 1.1 alnsn FAIL_IF(push_inst(compiler, ORI | S(src1) | A(dst) | IMM(compiler->imm))); 184 1.1 alnsn return push_inst(compiler, ORIS | S(dst) | A(dst) | IMM(compiler->imm >> 16)); 185 1.1 alnsn } 186 1.1 alnsn return push_inst(compiler, OR | RC(flags) | S(src1) | A(dst) | B(src2)); 187 1.1 alnsn 188 1.1 alnsn case SLJIT_XOR: 189 1.1 alnsn if (flags & ALT_FORM1) { 190 1.1 alnsn SLJIT_ASSERT(src2 == TMP_REG2); 191 1.1 alnsn return push_inst(compiler, XORI | S(src1) | A(dst) | compiler->imm); 192 1.1 alnsn } 193 1.1 alnsn if (flags & ALT_FORM2) { 194 1.1 alnsn SLJIT_ASSERT(src2 == TMP_REG2); 195 1.1 alnsn return push_inst(compiler, XORIS | S(src1) | A(dst) | compiler->imm); 196 1.1 alnsn } 197 1.1 alnsn if (flags & ALT_FORM3) { 198 1.1 alnsn SLJIT_ASSERT(src2 == TMP_REG2); 199 1.1 alnsn FAIL_IF(push_inst(compiler, XORI | S(src1) | A(dst) | IMM(compiler->imm))); 200 1.1 alnsn return push_inst(compiler, XORIS | S(dst) | A(dst) | IMM(compiler->imm >> 16)); 201 1.1 alnsn } 202 1.1 alnsn return push_inst(compiler, XOR | RC(flags) | S(src1) | A(dst) | B(src2)); 203 1.1 alnsn 204 1.1 alnsn case SLJIT_SHL: 205 1.1 alnsn if (flags & ALT_FORM1) { 206 1.1 alnsn SLJIT_ASSERT(src2 == TMP_REG2); 207 1.1 alnsn compiler->imm &= 0x1f; 208 1.1 alnsn return push_inst(compiler, RLWINM | RC(flags) | S(src1) | A(dst) | (compiler->imm << 11) | ((31 - compiler->imm) << 1)); 209 1.1 alnsn } 210 1.1 alnsn return push_inst(compiler, SLW | RC(flags) | S(src1) | A(dst) | B(src2)); 211 1.1 alnsn 212 1.1 alnsn case SLJIT_LSHR: 213 1.1 alnsn if (flags & ALT_FORM1) { 214 1.1 alnsn SLJIT_ASSERT(src2 == TMP_REG2); 215 1.1 alnsn compiler->imm &= 0x1f; 216 1.1 alnsn return push_inst(compiler, RLWINM | RC(flags) | S(src1) | A(dst) | (((32 - compiler->imm) & 0x1f) << 11) | (compiler->imm << 6) | (31 << 1)); 217 1.1 alnsn } 218 1.1 alnsn return push_inst(compiler, SRW | RC(flags) | S(src1) | A(dst) | B(src2)); 219 1.1 alnsn 220 1.1 alnsn case SLJIT_ASHR: 221 1.1 alnsn if (flags & ALT_FORM1) { 222 1.1 alnsn SLJIT_ASSERT(src2 == TMP_REG2); 223 1.1 alnsn compiler->imm &= 0x1f; 224 1.4 alnsn return push_inst(compiler, SRAWI | RC(flags) | S(src1) | A(dst) | (compiler->imm << 11)); 225 1.1 alnsn } 226 1.4 alnsn return push_inst(compiler, SRAW | RC(flags) | S(src1) | A(dst) | B(src2)); 227 1.1 alnsn } 228 1.1 alnsn 229 1.4 alnsn SLJIT_UNREACHABLE(); 230 1.1 alnsn return SLJIT_SUCCESS; 231 1.1 alnsn } 232 1.1 alnsn 233 1.3 alnsn static SLJIT_INLINE sljit_s32 emit_const(struct sljit_compiler *compiler, sljit_s32 reg, sljit_sw init_value) 234 1.1 alnsn { 235 1.1 alnsn FAIL_IF(push_inst(compiler, ADDIS | D(reg) | A(0) | IMM(init_value >> 16))); 236 1.1 alnsn return push_inst(compiler, ORI | S(reg) | A(reg) | IMM(init_value)); 237 1.1 alnsn } 238 1.1 alnsn 239 1.4 alnsn SLJIT_API_FUNC_ATTRIBUTE void sljit_set_jump_addr(sljit_uw addr, sljit_uw new_target, sljit_sw executable_offset) 240 1.1 alnsn { 241 1.4 alnsn sljit_ins *inst = (sljit_ins *)addr; 242 1.1 alnsn 243 1.4 alnsn inst[0] = (inst[0] & 0xffff0000) | ((new_target >> 16) & 0xffff); 244 1.4 alnsn inst[1] = (inst[1] & 0xffff0000) | (new_target & 0xffff); 245 1.4 alnsn inst = (sljit_ins *)SLJIT_ADD_EXEC_OFFSET(inst, executable_offset); 246 1.1 alnsn SLJIT_CACHE_FLUSH(inst, inst + 2); 247 1.1 alnsn } 248 1.1 alnsn 249 1.4 alnsn SLJIT_API_FUNC_ATTRIBUTE void sljit_set_const(sljit_uw addr, sljit_sw new_constant, sljit_sw executable_offset) 250 1.1 alnsn { 251 1.4 alnsn sljit_ins *inst = (sljit_ins *)addr; 252 1.1 alnsn 253 1.1 alnsn inst[0] = (inst[0] & 0xffff0000) | ((new_constant >> 16) & 0xffff); 254 1.1 alnsn inst[1] = (inst[1] & 0xffff0000) | (new_constant & 0xffff); 255 1.4 alnsn inst = (sljit_ins *)SLJIT_ADD_EXEC_OFFSET(inst, executable_offset); 256 1.1 alnsn SLJIT_CACHE_FLUSH(inst, inst + 2); 257 1.1 alnsn } 258