1 /* $NetBSD: sljitNativePPC_32.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 /* ppc 32-bit arch dependent functions. */ 30 31 static sljit_si load_immediate(struct sljit_compiler *compiler, sljit_si 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_si emit_single_op(struct sljit_compiler *compiler, sljit_si op, sljit_si flags, 47 sljit_si dst, sljit_si src1, sljit_si src2) 48 { 49 switch (op) { 50 case SLJIT_MOV: 51 case SLJIT_MOV_UI: 52 case SLJIT_MOV_SI: 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_UB: 60 case SLJIT_MOV_SB: 61 SLJIT_ASSERT(src1 == TMP_REG1); 62 if ((flags & (REG_DEST | REG2_SOURCE)) == (REG_DEST | REG2_SOURCE)) { 63 if (op == SLJIT_MOV_SB) 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_SB) 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_UH: 75 case SLJIT_MOV_SH: 76 SLJIT_ASSERT(src1 == TMP_REG1); 77 if ((flags & (REG_DEST | REG2_SOURCE)) == (REG_DEST | REG2_SOURCE)) { 78 if (op == SLJIT_MOV_SH) 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 if (flags & ALT_FORM1) { 125 FAIL_IF(push_inst(compiler, MFXER | D(0))); 126 FAIL_IF(push_inst(compiler, ADDE | D(dst) | A(src1) | B(src2))); 127 return push_inst(compiler, MTXER | S(0)); 128 } 129 return push_inst(compiler, ADDE | D(dst) | A(src1) | B(src2)); 130 131 case SLJIT_SUB: 132 if (flags & ALT_FORM1) { 133 /* Flags does not set: BIN_IMM_EXTS unnecessary. */ 134 SLJIT_ASSERT(src2 == TMP_REG2); 135 return push_inst(compiler, SUBFIC | D(dst) | A(src1) | compiler->imm); 136 } 137 if (flags & (ALT_FORM2 | ALT_FORM3)) { 138 SLJIT_ASSERT(src2 == TMP_REG2); 139 if (flags & ALT_FORM2) 140 FAIL_IF(push_inst(compiler, CMPI | CRD(0) | A(src1) | compiler->imm)); 141 if (flags & ALT_FORM3) 142 return push_inst(compiler, CMPLI | CRD(4) | A(src1) | compiler->imm); 143 return SLJIT_SUCCESS; 144 } 145 if (flags & (ALT_FORM4 | ALT_FORM5)) { 146 if (flags & ALT_FORM4) 147 FAIL_IF(push_inst(compiler, CMPL | CRD(4) | A(src1) | B(src2))); 148 if (flags & ALT_FORM5) 149 FAIL_IF(push_inst(compiler, CMP | CRD(0) | A(src1) | B(src2))); 150 return SLJIT_SUCCESS; 151 } 152 if (!(flags & ALT_SET_FLAGS)) 153 return push_inst(compiler, SUBF | D(dst) | A(src2) | B(src1)); 154 if (flags & ALT_FORM6) 155 FAIL_IF(push_inst(compiler, CMPL | CRD(4) | A(src1) | B(src2))); 156 return push_inst(compiler, SUBFC | OERC(ALT_SET_FLAGS) | D(dst) | A(src2) | B(src1)); 157 158 case SLJIT_SUBC: 159 if (flags & ALT_FORM1) { 160 FAIL_IF(push_inst(compiler, MFXER | D(0))); 161 FAIL_IF(push_inst(compiler, SUBFE | D(dst) | A(src2) | B(src1))); 162 return push_inst(compiler, MTXER | S(0)); 163 } 164 return push_inst(compiler, SUBFE | D(dst) | A(src2) | B(src1)); 165 166 case SLJIT_MUL: 167 if (flags & ALT_FORM1) { 168 SLJIT_ASSERT(src2 == TMP_REG2); 169 return push_inst(compiler, MULLI | D(dst) | A(src1) | compiler->imm); 170 } 171 return push_inst(compiler, MULLW | OERC(flags) | D(dst) | A(src2) | B(src1)); 172 173 case SLJIT_AND: 174 if (flags & ALT_FORM1) { 175 SLJIT_ASSERT(src2 == TMP_REG2); 176 return push_inst(compiler, ANDI | S(src1) | A(dst) | compiler->imm); 177 } 178 if (flags & ALT_FORM2) { 179 SLJIT_ASSERT(src2 == TMP_REG2); 180 return push_inst(compiler, ANDIS | S(src1) | A(dst) | compiler->imm); 181 } 182 return push_inst(compiler, AND | RC(flags) | S(src1) | A(dst) | B(src2)); 183 184 case SLJIT_OR: 185 if (flags & ALT_FORM1) { 186 SLJIT_ASSERT(src2 == TMP_REG2); 187 return push_inst(compiler, ORI | S(src1) | A(dst) | compiler->imm); 188 } 189 if (flags & ALT_FORM2) { 190 SLJIT_ASSERT(src2 == TMP_REG2); 191 return push_inst(compiler, ORIS | S(src1) | A(dst) | compiler->imm); 192 } 193 if (flags & ALT_FORM3) { 194 SLJIT_ASSERT(src2 == TMP_REG2); 195 FAIL_IF(push_inst(compiler, ORI | S(src1) | A(dst) | IMM(compiler->imm))); 196 return push_inst(compiler, ORIS | S(dst) | A(dst) | IMM(compiler->imm >> 16)); 197 } 198 return push_inst(compiler, OR | RC(flags) | S(src1) | A(dst) | B(src2)); 199 200 case SLJIT_XOR: 201 if (flags & ALT_FORM1) { 202 SLJIT_ASSERT(src2 == TMP_REG2); 203 return push_inst(compiler, XORI | S(src1) | A(dst) | compiler->imm); 204 } 205 if (flags & ALT_FORM2) { 206 SLJIT_ASSERT(src2 == TMP_REG2); 207 return push_inst(compiler, XORIS | S(src1) | A(dst) | compiler->imm); 208 } 209 if (flags & ALT_FORM3) { 210 SLJIT_ASSERT(src2 == TMP_REG2); 211 FAIL_IF(push_inst(compiler, XORI | S(src1) | A(dst) | IMM(compiler->imm))); 212 return push_inst(compiler, XORIS | S(dst) | A(dst) | IMM(compiler->imm >> 16)); 213 } 214 return push_inst(compiler, XOR | RC(flags) | S(src1) | A(dst) | B(src2)); 215 216 case SLJIT_SHL: 217 if (flags & ALT_FORM1) { 218 SLJIT_ASSERT(src2 == TMP_REG2); 219 compiler->imm &= 0x1f; 220 return push_inst(compiler, RLWINM | RC(flags) | S(src1) | A(dst) | (compiler->imm << 11) | ((31 - compiler->imm) << 1)); 221 } 222 return push_inst(compiler, SLW | RC(flags) | S(src1) | A(dst) | B(src2)); 223 224 case SLJIT_LSHR: 225 if (flags & ALT_FORM1) { 226 SLJIT_ASSERT(src2 == TMP_REG2); 227 compiler->imm &= 0x1f; 228 return push_inst(compiler, RLWINM | RC(flags) | S(src1) | A(dst) | (((32 - compiler->imm) & 0x1f) << 11) | (compiler->imm << 6) | (31 << 1)); 229 } 230 return push_inst(compiler, SRW | RC(flags) | S(src1) | A(dst) | B(src2)); 231 232 case SLJIT_ASHR: 233 if (flags & ALT_FORM3) 234 FAIL_IF(push_inst(compiler, MFXER | D(0))); 235 if (flags & ALT_FORM1) { 236 SLJIT_ASSERT(src2 == TMP_REG2); 237 compiler->imm &= 0x1f; 238 FAIL_IF(push_inst(compiler, SRAWI | RC(flags) | S(src1) | A(dst) | (compiler->imm << 11))); 239 } 240 else 241 FAIL_IF(push_inst(compiler, SRAW | RC(flags) | S(src1) | A(dst) | B(src2))); 242 return (flags & ALT_FORM3) ? push_inst(compiler, MTXER | S(0)) : SLJIT_SUCCESS; 243 } 244 245 SLJIT_ASSERT_STOP(); 246 return SLJIT_SUCCESS; 247 } 248 249 static SLJIT_INLINE sljit_si emit_const(struct sljit_compiler *compiler, sljit_si reg, sljit_sw init_value) 250 { 251 FAIL_IF(push_inst(compiler, ADDIS | D(reg) | A(0) | IMM(init_value >> 16))); 252 return push_inst(compiler, ORI | S(reg) | A(reg) | IMM(init_value)); 253 } 254 255 SLJIT_API_FUNC_ATTRIBUTE void sljit_set_jump_addr(sljit_uw addr, sljit_uw new_addr) 256 { 257 sljit_ins *inst = (sljit_ins*)addr; 258 259 inst[0] = (inst[0] & 0xffff0000) | ((new_addr >> 16) & 0xffff); 260 inst[1] = (inst[1] & 0xffff0000) | (new_addr & 0xffff); 261 SLJIT_CACHE_FLUSH(inst, inst + 2); 262 } 263 264 SLJIT_API_FUNC_ATTRIBUTE void sljit_set_const(sljit_uw addr, sljit_sw new_constant) 265 { 266 sljit_ins *inst = (sljit_ins*)addr; 267 268 inst[0] = (inst[0] & 0xffff0000) | ((new_constant >> 16) & 0xffff); 269 inst[1] = (inst[1] & 0xffff0000) | (new_constant & 0xffff); 270 SLJIT_CACHE_FLUSH(inst, inst + 2); 271 } 272