1e18e3516Sopenharmony_ci/* 2e18e3516Sopenharmony_ci * Stack-less Just-In-Time compiler 3e18e3516Sopenharmony_ci * 4e18e3516Sopenharmony_ci * Copyright Zoltan Herczeg (hzmester@freemail.hu). All rights reserved. 5e18e3516Sopenharmony_ci * 6e18e3516Sopenharmony_ci * Redistribution and use in source and binary forms, with or without modification, are 7e18e3516Sopenharmony_ci * permitted provided that the following conditions are met: 8e18e3516Sopenharmony_ci * 9e18e3516Sopenharmony_ci * 1. Redistributions of source code must retain the above copyright notice, this list of 10e18e3516Sopenharmony_ci * conditions and the following disclaimer. 11e18e3516Sopenharmony_ci * 12e18e3516Sopenharmony_ci * 2. Redistributions in binary form must reproduce the above copyright notice, this list 13e18e3516Sopenharmony_ci * of conditions and the following disclaimer in the documentation and/or other materials 14e18e3516Sopenharmony_ci * provided with the distribution. 15e18e3516Sopenharmony_ci * 16e18e3516Sopenharmony_ci * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) AND CONTRIBUTORS ``AS IS'' AND ANY 17e18e3516Sopenharmony_ci * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 18e18e3516Sopenharmony_ci * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT 19e18e3516Sopenharmony_ci * SHALL THE COPYRIGHT HOLDER(S) OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 20e18e3516Sopenharmony_ci * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED 21e18e3516Sopenharmony_ci * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR 22e18e3516Sopenharmony_ci * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 23e18e3516Sopenharmony_ci * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 24e18e3516Sopenharmony_ci * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25e18e3516Sopenharmony_ci */ 26e18e3516Sopenharmony_ci 27e18e3516Sopenharmony_cistatic sljit_s32 load_immediate(struct sljit_compiler *compiler, sljit_s32 dst_r, sljit_sw imm, sljit_s32 tmp_r) 28e18e3516Sopenharmony_ci{ 29e18e3516Sopenharmony_ci sljit_sw high; 30e18e3516Sopenharmony_ci 31e18e3516Sopenharmony_ci SLJIT_ASSERT(dst_r != tmp_r); 32e18e3516Sopenharmony_ci 33e18e3516Sopenharmony_ci if (imm <= SIMM_MAX && imm >= SIMM_MIN) 34e18e3516Sopenharmony_ci return push_inst(compiler, ADDI | RD(dst_r) | RS1(TMP_ZERO) | IMM_I(imm)); 35e18e3516Sopenharmony_ci 36e18e3516Sopenharmony_ci if (imm <= 0x7fffffffl && imm >= S32_MIN) { 37e18e3516Sopenharmony_ci if (imm > S32_MAX) { 38e18e3516Sopenharmony_ci SLJIT_ASSERT((imm & 0x800) != 0); 39e18e3516Sopenharmony_ci FAIL_IF(push_inst(compiler, LUI | RD(dst_r) | (sljit_ins)0x80000000u)); 40e18e3516Sopenharmony_ci return push_inst(compiler, XORI | RD(dst_r) | RS1(dst_r) | IMM_I(imm)); 41e18e3516Sopenharmony_ci } 42e18e3516Sopenharmony_ci 43e18e3516Sopenharmony_ci if ((imm & 0x800) != 0) 44e18e3516Sopenharmony_ci imm += 0x1000; 45e18e3516Sopenharmony_ci 46e18e3516Sopenharmony_ci FAIL_IF(push_inst(compiler, LUI | RD(dst_r) | (sljit_ins)(imm & ~0xfff))); 47e18e3516Sopenharmony_ci 48e18e3516Sopenharmony_ci if ((imm & 0xfff) == 0) 49e18e3516Sopenharmony_ci return SLJIT_SUCCESS; 50e18e3516Sopenharmony_ci 51e18e3516Sopenharmony_ci return push_inst(compiler, ADDI | RD(dst_r) | RS1(dst_r) | IMM_I(imm)); 52e18e3516Sopenharmony_ci } 53e18e3516Sopenharmony_ci 54e18e3516Sopenharmony_ci /* Trailing zeroes could be used to produce shifted immediates. */ 55e18e3516Sopenharmony_ci 56e18e3516Sopenharmony_ci if (imm <= 0x7ffffffffffl && imm >= -0x80000000000l) { 57e18e3516Sopenharmony_ci high = imm >> 12; 58e18e3516Sopenharmony_ci 59e18e3516Sopenharmony_ci if (imm & 0x800) 60e18e3516Sopenharmony_ci high = ~high; 61e18e3516Sopenharmony_ci 62e18e3516Sopenharmony_ci if (high > S32_MAX) { 63e18e3516Sopenharmony_ci SLJIT_ASSERT((high & 0x800) != 0); 64e18e3516Sopenharmony_ci FAIL_IF(push_inst(compiler, LUI | RD(dst_r) | (sljit_ins)0x80000000u)); 65e18e3516Sopenharmony_ci FAIL_IF(push_inst(compiler, XORI | RD(dst_r) | RS1(dst_r) | IMM_I(high))); 66e18e3516Sopenharmony_ci } else { 67e18e3516Sopenharmony_ci if ((high & 0x800) != 0) 68e18e3516Sopenharmony_ci high += 0x1000; 69e18e3516Sopenharmony_ci 70e18e3516Sopenharmony_ci FAIL_IF(push_inst(compiler, LUI | RD(dst_r) | (sljit_ins)(high & ~0xfff))); 71e18e3516Sopenharmony_ci 72e18e3516Sopenharmony_ci if ((high & 0xfff) != 0) 73e18e3516Sopenharmony_ci FAIL_IF(push_inst(compiler, ADDI | RD(dst_r) | RS1(dst_r) | IMM_I(high))); 74e18e3516Sopenharmony_ci } 75e18e3516Sopenharmony_ci 76e18e3516Sopenharmony_ci FAIL_IF(push_inst(compiler, SLLI | RD(dst_r) | RS1(dst_r) | IMM_I(12))); 77e18e3516Sopenharmony_ci 78e18e3516Sopenharmony_ci if ((imm & 0xfff) != 0) 79e18e3516Sopenharmony_ci return push_inst(compiler, XORI | RD(dst_r) | RS1(dst_r) | IMM_I(imm)); 80e18e3516Sopenharmony_ci 81e18e3516Sopenharmony_ci return SLJIT_SUCCESS; 82e18e3516Sopenharmony_ci } 83e18e3516Sopenharmony_ci 84e18e3516Sopenharmony_ci high = imm >> 32; 85e18e3516Sopenharmony_ci imm = (sljit_s32)imm; 86e18e3516Sopenharmony_ci 87e18e3516Sopenharmony_ci if ((imm & 0x80000000l) != 0) 88e18e3516Sopenharmony_ci high = ~high; 89e18e3516Sopenharmony_ci 90e18e3516Sopenharmony_ci if (high <= 0x7ffff && high >= -0x80000) { 91e18e3516Sopenharmony_ci FAIL_IF(push_inst(compiler, LUI | RD(tmp_r) | (sljit_ins)(high << 12))); 92e18e3516Sopenharmony_ci high = 0x1000; 93e18e3516Sopenharmony_ci } else { 94e18e3516Sopenharmony_ci if ((high & 0x800) != 0) 95e18e3516Sopenharmony_ci high += 0x1000; 96e18e3516Sopenharmony_ci 97e18e3516Sopenharmony_ci FAIL_IF(push_inst(compiler, LUI | RD(tmp_r) | (sljit_ins)(high & ~0xfff))); 98e18e3516Sopenharmony_ci high &= 0xfff; 99e18e3516Sopenharmony_ci } 100e18e3516Sopenharmony_ci 101e18e3516Sopenharmony_ci if (imm <= SIMM_MAX && imm >= SIMM_MIN) { 102e18e3516Sopenharmony_ci FAIL_IF(push_inst(compiler, ADDI | RD(dst_r) | RS1(TMP_ZERO) | IMM_I(imm))); 103e18e3516Sopenharmony_ci imm = 0; 104e18e3516Sopenharmony_ci } else if (imm > S32_MAX) { 105e18e3516Sopenharmony_ci SLJIT_ASSERT((imm & 0x800) != 0); 106e18e3516Sopenharmony_ci 107e18e3516Sopenharmony_ci FAIL_IF(push_inst(compiler, LUI | RD(dst_r) | (sljit_ins)0x80000000u)); 108e18e3516Sopenharmony_ci imm = 0x1000 | (imm & 0xfff); 109e18e3516Sopenharmony_ci } else { 110e18e3516Sopenharmony_ci if ((imm & 0x800) != 0) 111e18e3516Sopenharmony_ci imm += 0x1000; 112e18e3516Sopenharmony_ci 113e18e3516Sopenharmony_ci FAIL_IF(push_inst(compiler, LUI | RD(dst_r) | (sljit_ins)(imm & ~0xfff))); 114e18e3516Sopenharmony_ci imm &= 0xfff; 115e18e3516Sopenharmony_ci } 116e18e3516Sopenharmony_ci 117e18e3516Sopenharmony_ci if ((high & 0xfff) != 0) 118e18e3516Sopenharmony_ci FAIL_IF(push_inst(compiler, ADDI | RD(tmp_r) | RS1(tmp_r) | IMM_I(high))); 119e18e3516Sopenharmony_ci 120e18e3516Sopenharmony_ci if (imm & 0x1000) 121e18e3516Sopenharmony_ci FAIL_IF(push_inst(compiler, XORI | RD(dst_r) | RS1(dst_r) | IMM_I(imm))); 122e18e3516Sopenharmony_ci else if (imm != 0) 123e18e3516Sopenharmony_ci FAIL_IF(push_inst(compiler, ADDI | RD(dst_r) | RS1(dst_r) | IMM_I(imm))); 124e18e3516Sopenharmony_ci 125e18e3516Sopenharmony_ci FAIL_IF(push_inst(compiler, SLLI | RD(tmp_r) | RS1(tmp_r) | IMM_I((high & 0x1000) ? 20 : 32))); 126e18e3516Sopenharmony_ci return push_inst(compiler, XOR | RD(dst_r) | RS1(dst_r) | RS2(tmp_r)); 127e18e3516Sopenharmony_ci} 128e18e3516Sopenharmony_ci 129e18e3516Sopenharmony_cistatic SLJIT_INLINE sljit_s32 emit_const(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw init_value, sljit_ins last_ins) 130e18e3516Sopenharmony_ci{ 131e18e3516Sopenharmony_ci sljit_sw high; 132e18e3516Sopenharmony_ci 133e18e3516Sopenharmony_ci if ((init_value & 0x800) != 0) 134e18e3516Sopenharmony_ci init_value += 0x1000; 135e18e3516Sopenharmony_ci 136e18e3516Sopenharmony_ci high = init_value >> 32; 137e18e3516Sopenharmony_ci 138e18e3516Sopenharmony_ci if ((init_value & 0x80000000l) != 0) 139e18e3516Sopenharmony_ci high = ~high; 140e18e3516Sopenharmony_ci 141e18e3516Sopenharmony_ci if ((high & 0x800) != 0) 142e18e3516Sopenharmony_ci high += 0x1000; 143e18e3516Sopenharmony_ci 144e18e3516Sopenharmony_ci FAIL_IF(push_inst(compiler, LUI | RD(TMP_REG3) | (sljit_ins)(high & ~0xfff))); 145e18e3516Sopenharmony_ci FAIL_IF(push_inst(compiler, ADDI | RD(TMP_REG3) | RS1(TMP_REG3) | IMM_I(high))); 146e18e3516Sopenharmony_ci FAIL_IF(push_inst(compiler, LUI | RD(dst) | (sljit_ins)(init_value & ~0xfff))); 147e18e3516Sopenharmony_ci FAIL_IF(push_inst(compiler, SLLI | RD(TMP_REG3) | RS1(TMP_REG3) | IMM_I(32))); 148e18e3516Sopenharmony_ci FAIL_IF(push_inst(compiler, XOR | RD(dst) | RS1(dst) | RS2(TMP_REG3))); 149e18e3516Sopenharmony_ci return push_inst(compiler, last_ins | RS1(dst) | IMM_I(init_value)); 150e18e3516Sopenharmony_ci} 151e18e3516Sopenharmony_ci 152e18e3516Sopenharmony_ciSLJIT_API_FUNC_ATTRIBUTE void sljit_set_jump_addr(sljit_uw addr, sljit_uw new_target, sljit_sw executable_offset) 153e18e3516Sopenharmony_ci{ 154e18e3516Sopenharmony_ci sljit_ins *inst = (sljit_ins*)addr; 155e18e3516Sopenharmony_ci sljit_sw high; 156e18e3516Sopenharmony_ci SLJIT_UNUSED_ARG(executable_offset); 157e18e3516Sopenharmony_ci 158e18e3516Sopenharmony_ci if ((new_target & 0x800) != 0) 159e18e3516Sopenharmony_ci new_target += 0x1000; 160e18e3516Sopenharmony_ci 161e18e3516Sopenharmony_ci high = (sljit_sw)new_target >> 32; 162e18e3516Sopenharmony_ci 163e18e3516Sopenharmony_ci if ((new_target & 0x80000000l) != 0) 164e18e3516Sopenharmony_ci high = ~high; 165e18e3516Sopenharmony_ci 166e18e3516Sopenharmony_ci if ((high & 0x800) != 0) 167e18e3516Sopenharmony_ci high += 0x1000; 168e18e3516Sopenharmony_ci 169e18e3516Sopenharmony_ci SLJIT_UPDATE_WX_FLAGS(inst, inst + 5, 0); 170e18e3516Sopenharmony_ci 171e18e3516Sopenharmony_ci SLJIT_ASSERT((inst[0] & 0x7f) == LUI); 172e18e3516Sopenharmony_ci inst[0] = (inst[0] & 0xfff) | (sljit_ins)(high & ~0xfff); 173e18e3516Sopenharmony_ci SLJIT_ASSERT((inst[1] & 0x707f) == ADDI); 174e18e3516Sopenharmony_ci inst[1] = (inst[1] & 0xfffff) | IMM_I(high); 175e18e3516Sopenharmony_ci SLJIT_ASSERT((inst[2] & 0x7f) == LUI); 176e18e3516Sopenharmony_ci inst[2] = (inst[2] & 0xfff) | (sljit_ins)((sljit_sw)new_target & ~0xfff); 177e18e3516Sopenharmony_ci SLJIT_ASSERT((inst[5] & 0x707f) == ADDI || (inst[5] & 0x707f) == JALR); 178e18e3516Sopenharmony_ci inst[5] = (inst[5] & 0xfffff) | IMM_I(new_target); 179e18e3516Sopenharmony_ci SLJIT_UPDATE_WX_FLAGS(inst, inst + 5, 1); 180e18e3516Sopenharmony_ci 181e18e3516Sopenharmony_ci inst = (sljit_ins *)SLJIT_ADD_EXEC_OFFSET(inst, executable_offset); 182e18e3516Sopenharmony_ci SLJIT_CACHE_FLUSH(inst, inst + 5); 183e18e3516Sopenharmony_ci} 184