Annotation of embedaddon/pcre/sljit/sljitNativePPC_32.c, revision 1.1.1.3
1.1 misho 1: /*
2: * Stack-less Just-In-Time compiler
3: *
1.1.1.2 misho 4: * Copyright 2009-2012 Zoltan Herczeg (hzmester@freemail.hu). All rights reserved.
1.1 misho 5: *
6: * Redistribution and use in source and binary forms, with or without modification, are
7: * permitted provided that the following conditions are met:
8: *
9: * 1. Redistributions of source code must retain the above copyright notice, this list of
10: * conditions and the following disclaimer.
11: *
12: * 2. Redistributions in binary form must reproduce the above copyright notice, this list
13: * of conditions and the following disclaimer in the documentation and/or other materials
14: * provided with the distribution.
15: *
16: * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) AND CONTRIBUTORS ``AS IS'' AND ANY
17: * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
18: * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
19: * SHALL THE COPYRIGHT HOLDER(S) OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
20: * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
21: * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
22: * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
23: * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
24: * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25: */
26:
27: /* ppc 32-bit arch dependent functions. */
28:
1.1.1.3 ! misho 29: static sljit_si load_immediate(struct sljit_compiler *compiler, sljit_si reg, sljit_sw imm)
1.1 misho 30: {
31: if (imm <= SIMM_MAX && imm >= SIMM_MIN)
32: return push_inst(compiler, ADDI | D(reg) | A(0) | IMM(imm));
33:
1.1.1.2 misho 34: if (!(imm & ~0xffff))
35: return push_inst(compiler, ORI | S(ZERO_REG) | A(reg) | IMM(imm));
36:
1.1 misho 37: FAIL_IF(push_inst(compiler, ADDIS | D(reg) | A(0) | IMM(imm >> 16)));
38: return (imm & 0xffff) ? push_inst(compiler, ORI | S(reg) | A(reg) | IMM(imm)) : SLJIT_SUCCESS;
39: }
40:
41: #define INS_CLEAR_LEFT(dst, src, from) \
42: (RLWINM | S(src) | A(dst) | ((from) << 6) | (31 << 1))
43:
1.1.1.3 ! misho 44: static SLJIT_INLINE sljit_si emit_single_op(struct sljit_compiler *compiler, sljit_si op, sljit_si flags,
! 45: sljit_si dst, sljit_si src1, sljit_si src2)
1.1 misho 46: {
47: switch (op) {
1.1.1.3 ! misho 48: case SLJIT_MOV:
! 49: case SLJIT_MOV_UI:
! 50: case SLJIT_MOV_SI:
! 51: case SLJIT_MOV_P:
! 52: SLJIT_ASSERT(src1 == TMP_REG1);
! 53: if (dst != src2)
! 54: return push_inst(compiler, OR | S(src2) | A(dst) | B(src2));
! 55: return SLJIT_SUCCESS;
! 56:
! 57: case SLJIT_MOV_UB:
! 58: case SLJIT_MOV_SB:
! 59: SLJIT_ASSERT(src1 == TMP_REG1);
! 60: if ((flags & (REG_DEST | REG2_SOURCE)) == (REG_DEST | REG2_SOURCE)) {
! 61: if (op == SLJIT_MOV_SB)
! 62: return push_inst(compiler, EXTSB | S(src2) | A(dst));
! 63: return push_inst(compiler, INS_CLEAR_LEFT(dst, src2, 24));
! 64: }
! 65: else if ((flags & REG_DEST) && op == SLJIT_MOV_SB)
! 66: return push_inst(compiler, EXTSB | S(src2) | A(dst));
! 67: else {
! 68: SLJIT_ASSERT(dst == src2);
! 69: }
! 70: return SLJIT_SUCCESS;
! 71:
! 72: case SLJIT_MOV_UH:
! 73: case SLJIT_MOV_SH:
! 74: SLJIT_ASSERT(src1 == TMP_REG1);
! 75: if ((flags & (REG_DEST | REG2_SOURCE)) == (REG_DEST | REG2_SOURCE)) {
! 76: if (op == SLJIT_MOV_SH)
! 77: return push_inst(compiler, EXTSH | S(src2) | A(dst));
! 78: return push_inst(compiler, INS_CLEAR_LEFT(dst, src2, 16));
! 79: }
! 80: else {
! 81: SLJIT_ASSERT(dst == src2);
! 82: }
! 83: return SLJIT_SUCCESS;
! 84:
! 85: case SLJIT_NOT:
! 86: SLJIT_ASSERT(src1 == TMP_REG1);
! 87: return push_inst(compiler, NOR | RC(flags) | S(src2) | A(dst) | B(src2));
! 88:
! 89: case SLJIT_NEG:
! 90: SLJIT_ASSERT(src1 == TMP_REG1);
! 91: return push_inst(compiler, NEG | OERC(flags) | D(dst) | A(src2));
! 92:
! 93: case SLJIT_CLZ:
! 94: SLJIT_ASSERT(src1 == TMP_REG1);
! 95: return push_inst(compiler, CNTLZW | RC(flags) | S(src2) | A(dst));
! 96:
1.1 misho 97: case SLJIT_ADD:
98: if (flags & ALT_FORM1) {
1.1.1.2 misho 99: /* Flags does not set: BIN_IMM_EXTS unnecessary. */
1.1 misho 100: SLJIT_ASSERT(src2 == TMP_REG2);
101: return push_inst(compiler, ADDI | D(dst) | A(src1) | compiler->imm);
102: }
103: if (flags & ALT_FORM2) {
1.1.1.2 misho 104: /* Flags does not set: BIN_IMM_EXTS unnecessary. */
1.1 misho 105: SLJIT_ASSERT(src2 == TMP_REG2);
106: return push_inst(compiler, ADDIS | D(dst) | A(src1) | compiler->imm);
107: }
108: if (flags & ALT_FORM3) {
109: SLJIT_ASSERT(src2 == TMP_REG2);
110: return push_inst(compiler, ADDIC | D(dst) | A(src1) | compiler->imm);
111: }
1.1.1.2 misho 112: if (flags & ALT_FORM4) {
113: /* Flags does not set: BIN_IMM_EXTS unnecessary. */
114: FAIL_IF(push_inst(compiler, ADDI | D(dst) | A(src1) | (compiler->imm & 0xffff)));
115: return push_inst(compiler, ADDIS | D(dst) | A(dst) | (((compiler->imm >> 16) & 0xffff) + ((compiler->imm >> 15) & 0x1)));
116: }
1.1 misho 117: if (!(flags & ALT_SET_FLAGS))
118: return push_inst(compiler, ADD | D(dst) | A(src1) | B(src2));
119: return push_inst(compiler, ADDC | OERC(ALT_SET_FLAGS) | D(dst) | A(src1) | B(src2));
120:
121: case SLJIT_ADDC:
122: if (flags & ALT_FORM1) {
1.1.1.3 ! misho 123: FAIL_IF(push_inst(compiler, MFXER | D(0)));
1.1 misho 124: FAIL_IF(push_inst(compiler, ADDE | D(dst) | A(src1) | B(src2)));
125: return push_inst(compiler, MTXER | S(0));
126: }
127: return push_inst(compiler, ADDE | D(dst) | A(src1) | B(src2));
128:
129: case SLJIT_SUB:
130: if (flags & ALT_FORM1) {
1.1.1.2 misho 131: /* Flags does not set: BIN_IMM_EXTS unnecessary. */
1.1 misho 132: SLJIT_ASSERT(src2 == TMP_REG2);
133: return push_inst(compiler, SUBFIC | D(dst) | A(src1) | compiler->imm);
134: }
1.1.1.2 misho 135: if (flags & (ALT_FORM2 | ALT_FORM3)) {
1.1 misho 136: SLJIT_ASSERT(src2 == TMP_REG2);
1.1.1.2 misho 137: if (flags & ALT_FORM2)
138: FAIL_IF(push_inst(compiler, CMPI | CRD(0) | A(src1) | compiler->imm));
139: if (flags & ALT_FORM3)
140: return push_inst(compiler, CMPLI | CRD(4) | A(src1) | compiler->imm);
141: return SLJIT_SUCCESS;
142: }
143: if (flags & (ALT_FORM4 | ALT_FORM5)) {
144: if (flags & ALT_FORM4)
145: FAIL_IF(push_inst(compiler, CMPL | CRD(4) | A(src1) | B(src2)));
146: if (flags & ALT_FORM5)
147: FAIL_IF(push_inst(compiler, CMP | CRD(0) | A(src1) | B(src2)));
148: return SLJIT_SUCCESS;
1.1 misho 149: }
150: if (!(flags & ALT_SET_FLAGS))
151: return push_inst(compiler, SUBF | D(dst) | A(src2) | B(src1));
1.1.1.2 misho 152: if (flags & ALT_FORM6)
1.1 misho 153: FAIL_IF(push_inst(compiler, CMPL | CRD(4) | A(src1) | B(src2)));
154: return push_inst(compiler, SUBFC | OERC(ALT_SET_FLAGS) | D(dst) | A(src2) | B(src1));
155:
156: case SLJIT_SUBC:
157: if (flags & ALT_FORM1) {
1.1.1.3 ! misho 158: FAIL_IF(push_inst(compiler, MFXER | D(0)));
1.1 misho 159: FAIL_IF(push_inst(compiler, SUBFE | D(dst) | A(src2) | B(src1)));
160: return push_inst(compiler, MTXER | S(0));
161: }
162: return push_inst(compiler, SUBFE | D(dst) | A(src2) | B(src1));
163:
164: case SLJIT_MUL:
165: if (flags & ALT_FORM1) {
166: SLJIT_ASSERT(src2 == TMP_REG2);
167: return push_inst(compiler, MULLI | D(dst) | A(src1) | compiler->imm);
168: }
169: return push_inst(compiler, MULLW | OERC(flags) | D(dst) | A(src2) | B(src1));
170:
171: case SLJIT_AND:
172: if (flags & ALT_FORM1) {
173: SLJIT_ASSERT(src2 == TMP_REG2);
174: return push_inst(compiler, ANDI | S(src1) | A(dst) | compiler->imm);
175: }
176: if (flags & ALT_FORM2) {
177: SLJIT_ASSERT(src2 == TMP_REG2);
178: return push_inst(compiler, ANDIS | S(src1) | A(dst) | compiler->imm);
179: }
180: return push_inst(compiler, AND | RC(flags) | S(src1) | A(dst) | B(src2));
181:
182: case SLJIT_OR:
183: if (flags & ALT_FORM1) {
184: SLJIT_ASSERT(src2 == TMP_REG2);
185: return push_inst(compiler, ORI | S(src1) | A(dst) | compiler->imm);
186: }
187: if (flags & ALT_FORM2) {
188: SLJIT_ASSERT(src2 == TMP_REG2);
189: return push_inst(compiler, ORIS | S(src1) | A(dst) | compiler->imm);
190: }
191: if (flags & ALT_FORM3) {
192: SLJIT_ASSERT(src2 == TMP_REG2);
193: FAIL_IF(push_inst(compiler, ORI | S(src1) | A(dst) | IMM(compiler->imm)));
194: return push_inst(compiler, ORIS | S(dst) | A(dst) | IMM(compiler->imm >> 16));
195: }
196: return push_inst(compiler, OR | RC(flags) | S(src1) | A(dst) | B(src2));
197:
198: case SLJIT_XOR:
199: if (flags & ALT_FORM1) {
200: SLJIT_ASSERT(src2 == TMP_REG2);
201: return push_inst(compiler, XORI | S(src1) | A(dst) | compiler->imm);
202: }
203: if (flags & ALT_FORM2) {
204: SLJIT_ASSERT(src2 == TMP_REG2);
205: return push_inst(compiler, XORIS | S(src1) | A(dst) | compiler->imm);
206: }
207: if (flags & ALT_FORM3) {
208: SLJIT_ASSERT(src2 == TMP_REG2);
209: FAIL_IF(push_inst(compiler, XORI | S(src1) | A(dst) | IMM(compiler->imm)));
210: return push_inst(compiler, XORIS | S(dst) | A(dst) | IMM(compiler->imm >> 16));
211: }
212: return push_inst(compiler, XOR | RC(flags) | S(src1) | A(dst) | B(src2));
213:
214: case SLJIT_SHL:
215: if (flags & ALT_FORM1) {
216: SLJIT_ASSERT(src2 == TMP_REG2);
217: compiler->imm &= 0x1f;
218: return push_inst(compiler, RLWINM | RC(flags) | S(src1) | A(dst) | (compiler->imm << 11) | ((31 - compiler->imm) << 1));
219: }
220: return push_inst(compiler, SLW | RC(flags) | S(src1) | A(dst) | B(src2));
221:
222: case SLJIT_LSHR:
223: if (flags & ALT_FORM1) {
224: SLJIT_ASSERT(src2 == TMP_REG2);
225: compiler->imm &= 0x1f;
226: return push_inst(compiler, RLWINM | RC(flags) | S(src1) | A(dst) | (((32 - compiler->imm) & 0x1f) << 11) | (compiler->imm << 6) | (31 << 1));
227: }
228: return push_inst(compiler, SRW | RC(flags) | S(src1) | A(dst) | B(src2));
229:
230: case SLJIT_ASHR:
1.1.1.3 ! misho 231: if (flags & ALT_FORM3)
! 232: FAIL_IF(push_inst(compiler, MFXER | D(0)));
1.1 misho 233: if (flags & ALT_FORM1) {
234: SLJIT_ASSERT(src2 == TMP_REG2);
235: compiler->imm &= 0x1f;
1.1.1.3 ! misho 236: FAIL_IF(push_inst(compiler, SRAWI | RC(flags) | S(src1) | A(dst) | (compiler->imm << 11)));
1.1 misho 237: }
1.1.1.3 ! misho 238: else
! 239: FAIL_IF(push_inst(compiler, SRAW | RC(flags) | S(src1) | A(dst) | B(src2)));
! 240: return (flags & ALT_FORM3) ? push_inst(compiler, MTXER | S(0)) : SLJIT_SUCCESS;
1.1 misho 241: }
242:
243: SLJIT_ASSERT_STOP();
244: return SLJIT_SUCCESS;
245: }
246:
1.1.1.3 ! misho 247: static SLJIT_INLINE sljit_si emit_const(struct sljit_compiler *compiler, sljit_si reg, sljit_sw init_value)
1.1 misho 248: {
249: FAIL_IF(push_inst(compiler, ADDIS | D(reg) | A(0) | IMM(init_value >> 16)));
250: return push_inst(compiler, ORI | S(reg) | A(reg) | IMM(init_value));
251: }
252:
253: SLJIT_API_FUNC_ATTRIBUTE void sljit_set_jump_addr(sljit_uw addr, sljit_uw new_addr)
254: {
255: sljit_ins *inst = (sljit_ins*)addr;
256:
257: inst[0] = (inst[0] & 0xffff0000) | ((new_addr >> 16) & 0xffff);
258: inst[1] = (inst[1] & 0xffff0000) | (new_addr & 0xffff);
259: SLJIT_CACHE_FLUSH(inst, inst + 2);
260: }
261:
1.1.1.3 ! misho 262: SLJIT_API_FUNC_ATTRIBUTE void sljit_set_const(sljit_uw addr, sljit_sw new_constant)
1.1 misho 263: {
264: sljit_ins *inst = (sljit_ins*)addr;
265:
266: inst[0] = (inst[0] & 0xffff0000) | ((new_constant >> 16) & 0xffff);
267: inst[1] = (inst[1] & 0xffff0000) | (new_constant & 0xffff);
268: SLJIT_CACHE_FLUSH(inst, inst + 2);
269: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>