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