1 1.4 alnsn /* $NetBSD: sljitNativeSPARC_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.3 alnsn static sljit_s32 load_immediate(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw imm) 30 1.1 alnsn { 31 1.1 alnsn if (imm <= SIMM_MAX && imm >= SIMM_MIN) 32 1.1 alnsn return push_inst(compiler, OR | D(dst) | S1(0) | IMM(imm), DR(dst)); 33 1.1 alnsn 34 1.1 alnsn FAIL_IF(push_inst(compiler, SETHI | D(dst) | ((imm >> 10) & 0x3fffff), DR(dst))); 35 1.1 alnsn return (imm & 0x3ff) ? push_inst(compiler, OR | D(dst) | S1(dst) | IMM_ARG | (imm & 0x3ff), DR(dst)) : SLJIT_SUCCESS; 36 1.1 alnsn } 37 1.1 alnsn 38 1.1 alnsn #define ARG2(flags, src2) ((flags & SRC2_IMM) ? IMM(src2) : S2(src2)) 39 1.1 alnsn 40 1.3 alnsn static SLJIT_INLINE sljit_s32 emit_single_op(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 flags, 41 1.3 alnsn sljit_s32 dst, sljit_s32 src1, sljit_sw src2) 42 1.1 alnsn { 43 1.1 alnsn SLJIT_COMPILE_ASSERT(ICC_IS_SET == SET_FLAGS, icc_is_set_and_set_flags_must_be_the_same); 44 1.1 alnsn 45 1.1 alnsn switch (op) { 46 1.1 alnsn case SLJIT_MOV: 47 1.3 alnsn case SLJIT_MOV_U32: 48 1.3 alnsn case SLJIT_MOV_S32: 49 1.2 alnsn case SLJIT_MOV_P: 50 1.1 alnsn SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & SRC2_IMM)); 51 1.1 alnsn if (dst != src2) 52 1.1 alnsn return push_inst(compiler, OR | D(dst) | S1(0) | S2(src2), DR(dst)); 53 1.1 alnsn return SLJIT_SUCCESS; 54 1.1 alnsn 55 1.3 alnsn case SLJIT_MOV_U8: 56 1.3 alnsn case SLJIT_MOV_S8: 57 1.1 alnsn SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & SRC2_IMM)); 58 1.1 alnsn if ((flags & (REG_DEST | REG2_SOURCE)) == (REG_DEST | REG2_SOURCE)) { 59 1.3 alnsn if (op == SLJIT_MOV_U8) 60 1.1 alnsn return push_inst(compiler, AND | D(dst) | S1(src2) | IMM(0xff), DR(dst)); 61 1.1 alnsn FAIL_IF(push_inst(compiler, SLL | D(dst) | S1(src2) | IMM(24), DR(dst))); 62 1.1 alnsn return push_inst(compiler, SRA | D(dst) | S1(dst) | IMM(24), DR(dst)); 63 1.1 alnsn } 64 1.1 alnsn else if (dst != src2) 65 1.4 alnsn SLJIT_UNREACHABLE(); 66 1.1 alnsn return SLJIT_SUCCESS; 67 1.1 alnsn 68 1.3 alnsn case SLJIT_MOV_U16: 69 1.3 alnsn case SLJIT_MOV_S16: 70 1.1 alnsn SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & SRC2_IMM)); 71 1.1 alnsn if ((flags & (REG_DEST | REG2_SOURCE)) == (REG_DEST | REG2_SOURCE)) { 72 1.1 alnsn FAIL_IF(push_inst(compiler, SLL | D(dst) | S1(src2) | IMM(16), DR(dst))); 73 1.3 alnsn return push_inst(compiler, (op == SLJIT_MOV_S16 ? SRA : SRL) | D(dst) | S1(dst) | IMM(16), DR(dst)); 74 1.1 alnsn } 75 1.1 alnsn else if (dst != src2) 76 1.4 alnsn SLJIT_UNREACHABLE(); 77 1.1 alnsn return SLJIT_SUCCESS; 78 1.1 alnsn 79 1.1 alnsn case SLJIT_NOT: 80 1.1 alnsn SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & SRC2_IMM)); 81 1.1 alnsn return push_inst(compiler, XNOR | (flags & SET_FLAGS) | D(dst) | S1(0) | S2(src2), DR(dst) | (flags & SET_FLAGS)); 82 1.1 alnsn 83 1.1 alnsn case SLJIT_CLZ: 84 1.1 alnsn SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & SRC2_IMM)); 85 1.1 alnsn /* sparc 32 does not support SLJIT_KEEP_FLAGS. Not sure I can fix this. */ 86 1.1 alnsn FAIL_IF(push_inst(compiler, SUB | SET_FLAGS | D(0) | S1(src2) | S2(0), SET_FLAGS)); 87 1.1 alnsn FAIL_IF(push_inst(compiler, OR | D(TMP_REG1) | S1(0) | S2(src2), DR(TMP_REG1))); 88 1.1 alnsn FAIL_IF(push_inst(compiler, BICC | DA(0x1) | (7 & DISP_MASK), UNMOVABLE_INS)); 89 1.1 alnsn FAIL_IF(push_inst(compiler, OR | (flags & SET_FLAGS) | D(dst) | S1(0) | IMM(32), UNMOVABLE_INS | (flags & SET_FLAGS))); 90 1.1 alnsn FAIL_IF(push_inst(compiler, OR | D(dst) | S1(0) | IMM(-1), DR(dst))); 91 1.1 alnsn 92 1.1 alnsn /* Loop. */ 93 1.1 alnsn FAIL_IF(push_inst(compiler, SUB | SET_FLAGS | D(0) | S1(TMP_REG1) | S2(0), SET_FLAGS)); 94 1.1 alnsn FAIL_IF(push_inst(compiler, SLL | D(TMP_REG1) | S1(TMP_REG1) | IMM(1), DR(TMP_REG1))); 95 1.1 alnsn FAIL_IF(push_inst(compiler, BICC | DA(0xe) | (-2 & DISP_MASK), UNMOVABLE_INS)); 96 1.1 alnsn return push_inst(compiler, ADD | (flags & SET_FLAGS) | D(dst) | S1(dst) | IMM(1), UNMOVABLE_INS | (flags & SET_FLAGS)); 97 1.1 alnsn 98 1.1 alnsn case SLJIT_ADD: 99 1.1 alnsn return push_inst(compiler, ADD | (flags & SET_FLAGS) | D(dst) | S1(src1) | ARG2(flags, src2), DR(dst) | (flags & SET_FLAGS)); 100 1.1 alnsn 101 1.1 alnsn case SLJIT_ADDC: 102 1.1 alnsn return push_inst(compiler, ADDC | (flags & SET_FLAGS) | D(dst) | S1(src1) | ARG2(flags, src2), DR(dst) | (flags & SET_FLAGS)); 103 1.1 alnsn 104 1.1 alnsn case SLJIT_SUB: 105 1.1 alnsn return push_inst(compiler, SUB | (flags & SET_FLAGS) | D(dst) | S1(src1) | ARG2(flags, src2), DR(dst) | (flags & SET_FLAGS)); 106 1.1 alnsn 107 1.1 alnsn case SLJIT_SUBC: 108 1.1 alnsn return push_inst(compiler, SUBC | (flags & SET_FLAGS) | D(dst) | S1(src1) | ARG2(flags, src2), DR(dst) | (flags & SET_FLAGS)); 109 1.1 alnsn 110 1.1 alnsn case SLJIT_MUL: 111 1.1 alnsn FAIL_IF(push_inst(compiler, SMUL | D(dst) | S1(src1) | ARG2(flags, src2), DR(dst))); 112 1.1 alnsn if (!(flags & SET_FLAGS)) 113 1.1 alnsn return SLJIT_SUCCESS; 114 1.1 alnsn FAIL_IF(push_inst(compiler, SRA | D(TMP_REG1) | S1(dst) | IMM(31), DR(TMP_REG1))); 115 1.3 alnsn FAIL_IF(push_inst(compiler, RDY | D(TMP_LINK), DR(TMP_LINK))); 116 1.3 alnsn return push_inst(compiler, SUB | SET_FLAGS | D(0) | S1(TMP_REG1) | S2(TMP_LINK), MOVABLE_INS | SET_FLAGS); 117 1.1 alnsn 118 1.1 alnsn case SLJIT_AND: 119 1.1 alnsn return push_inst(compiler, AND | (flags & SET_FLAGS) | D(dst) | S1(src1) | ARG2(flags, src2), DR(dst) | (flags & SET_FLAGS)); 120 1.1 alnsn 121 1.1 alnsn case SLJIT_OR: 122 1.1 alnsn return push_inst(compiler, OR | (flags & SET_FLAGS) | D(dst) | S1(src1) | ARG2(flags, src2), DR(dst) | (flags & SET_FLAGS)); 123 1.1 alnsn 124 1.1 alnsn case SLJIT_XOR: 125 1.1 alnsn return push_inst(compiler, XOR | (flags & SET_FLAGS) | D(dst) | S1(src1) | ARG2(flags, src2), DR(dst) | (flags & SET_FLAGS)); 126 1.1 alnsn 127 1.1 alnsn case SLJIT_SHL: 128 1.1 alnsn FAIL_IF(push_inst(compiler, SLL | D(dst) | S1(src1) | ARG2(flags, src2), DR(dst))); 129 1.1 alnsn return !(flags & SET_FLAGS) ? SLJIT_SUCCESS : push_inst(compiler, SUB | SET_FLAGS | D(0) | S1(dst) | S2(0), SET_FLAGS); 130 1.1 alnsn 131 1.1 alnsn case SLJIT_LSHR: 132 1.1 alnsn FAIL_IF(push_inst(compiler, SRL | D(dst) | S1(src1) | ARG2(flags, src2), DR(dst))); 133 1.1 alnsn return !(flags & SET_FLAGS) ? SLJIT_SUCCESS : push_inst(compiler, SUB | SET_FLAGS | D(0) | S1(dst) | S2(0), SET_FLAGS); 134 1.1 alnsn 135 1.1 alnsn case SLJIT_ASHR: 136 1.1 alnsn FAIL_IF(push_inst(compiler, SRA | D(dst) | S1(src1) | ARG2(flags, src2), DR(dst))); 137 1.1 alnsn return !(flags & SET_FLAGS) ? SLJIT_SUCCESS : push_inst(compiler, SUB | SET_FLAGS | D(0) | S1(dst) | S2(0), SET_FLAGS); 138 1.1 alnsn } 139 1.1 alnsn 140 1.4 alnsn SLJIT_UNREACHABLE(); 141 1.1 alnsn return SLJIT_SUCCESS; 142 1.1 alnsn } 143 1.1 alnsn 144 1.3 alnsn static SLJIT_INLINE sljit_s32 emit_const(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw init_value) 145 1.1 alnsn { 146 1.1 alnsn FAIL_IF(push_inst(compiler, SETHI | D(dst) | ((init_value >> 10) & 0x3fffff), DR(dst))); 147 1.1 alnsn return push_inst(compiler, OR | D(dst) | S1(dst) | IMM_ARG | (init_value & 0x3ff), DR(dst)); 148 1.1 alnsn } 149 1.1 alnsn 150 1.4 alnsn SLJIT_API_FUNC_ATTRIBUTE void sljit_set_jump_addr(sljit_uw addr, sljit_uw new_target, sljit_sw executable_offset) 151 1.1 alnsn { 152 1.4 alnsn sljit_ins *inst = (sljit_ins *)addr; 153 1.1 alnsn 154 1.4 alnsn inst[0] = (inst[0] & 0xffc00000) | ((new_target >> 10) & 0x3fffff); 155 1.4 alnsn inst[1] = (inst[1] & 0xfffffc00) | (new_target & 0x3ff); 156 1.4 alnsn inst = (sljit_ins *)SLJIT_ADD_EXEC_OFFSET(inst, executable_offset); 157 1.1 alnsn SLJIT_CACHE_FLUSH(inst, inst + 2); 158 1.1 alnsn } 159 1.1 alnsn 160 1.4 alnsn SLJIT_API_FUNC_ATTRIBUTE void sljit_set_const(sljit_uw addr, sljit_sw new_constant, sljit_sw executable_offset) 161 1.1 alnsn { 162 1.4 alnsn sljit_ins *inst = (sljit_ins *)addr; 163 1.1 alnsn 164 1.1 alnsn inst[0] = (inst[0] & 0xffc00000) | ((new_constant >> 10) & 0x3fffff); 165 1.1 alnsn inst[1] = (inst[1] & 0xfffffc00) | (new_constant & 0x3ff); 166 1.4 alnsn inst = (sljit_ins *)SLJIT_ADD_EXEC_OFFSET(inst, executable_offset); 167 1.1 alnsn SLJIT_CACHE_FLUSH(inst, inst + 2); 168 1.1 alnsn } 169