Alien-LibJIT
view release on metacpan or search on metacpan
libjit/jit/jit-rules-x86-64.ins view on Meta::CPAN
[reg, reg] -> {
x86_64_add_reg_reg_size(inst, $1, $2, 4);
}
JIT_OP_ISUB:
[reg, imm] -> {
if($2 == 1)
{
x86_64_dec_reg_size(inst, $1, 4);
}
else
{
x86_64_sub_reg_imm_size(inst, $1, $2, 4);
}
}
[reg, local] -> {
x86_64_sub_reg_membase_size(inst, $1, X86_64_RBP, $2, 4);
}
[reg, reg] -> {
x86_64_sub_reg_reg_size(inst, $1, $2, 4);
}
JIT_OP_INEG:
[reg] -> {
x86_64_neg_reg_size(inst, $1, 4);
}
JIT_OP_IMUL: commutative
[reg, immzero] -> {
x86_64_clear_reg(inst, $1);
}
[reg, imm, if("$2 == -1")] -> {
x86_64_neg_reg_size(inst, $1, 4);
}
[reg, imm, if("$2 == 1")] -> {
}
[reg, imm, if("$2 == 2")] -> {
x86_64_add_reg_reg_size(inst, $1, $1, 4);
}
[reg, imm, if("(((jit_nuint)$2) & (((jit_nuint)$2) - 1)) == 0")] -> {
/* x & (x - 1) is equal to zero if x is a power of 2 */
jit_nuint shift, value = $2 >> 1;
for(shift = 0; value; value >>= 1)
{
++shift;
}
x86_64_shl_reg_imm_size(inst, $1, shift, 4);
}
[reg, imm] -> {
x86_64_imul_reg_reg_imm_size(inst, $1, $1, $2, 4);
}
[reg, local] -> {
x86_64_imul_reg_membase_size(inst, $1, X86_64_RBP, $2, 4);
}
[reg, reg] -> {
x86_64_imul_reg_reg_size(inst, $1, $2, 4);
}
JIT_OP_IDIV: more_space
[any, immzero] -> {
inst = throw_builtin(inst, func, JIT_RESULT_DIVISION_BY_ZERO);
}
[reg, imm, if("$2 == 1")] -> {
}
[reg, imm, if("$2 == -1")] -> {
/* Dividing by -1 gives an exception if the argument
is minint, or simply negates for other values */
jit_int min_int = jit_min_int;
unsigned char *patch;
x86_64_cmp_reg_imm_size(inst, $1, min_int, 4);
patch = inst;
x86_branch8(inst, X86_CC_NE, 0, 0);
inst = throw_builtin(inst, func, JIT_RESULT_ARITHMETIC);
x86_patch(patch, inst);
x86_64_neg_reg_size(inst, $1, 4);
}
[reg, imm, scratch reg, if("$2 == 2")] -> {
/* move the value to be divided to the temporary */
x86_64_mov_reg_reg_size(inst, $3, $1, 4);
/* shift the temporary to the 31 bits right */
/* The result is 1 for negative values and 0 for zero or */
/* positive values. (corrective value for negatives) */
x86_64_shr_reg_imm_size(inst, $3, 0x1f, 4);
/* Add the corrective value to the divident */
x86_64_add_reg_reg_size(inst, $1, $3, 4);
/* and do the right shift */
x86_64_sar_reg_imm_size(inst, $1, 1, 4);
}
[reg, imm, scratch reg, if("($2 > 0) && (((jit_nuint)$2) & (((jit_nuint)$2) - 1)) == 0")] -> {
/* x & (x - 1) is equal to zero if x is a power of 2 */
jit_nuint shift, corr, value = $2 >> 1;
for(shift = 0; value; value >>= 1)
{
++shift;
}
corr = $2 - 1;
x86_64_lea_membase_size(inst, $3, $1, corr, 4);
x86_64_test_reg_reg_size(inst, $1, $1, 4);
x86_64_cmov_reg_reg_size(inst, X86_CC_S, $1, $3, 1, 4);
x86_64_sar_reg_imm_size(inst, $1, shift, 4);
}
[reg("rax"), imm, scratch dreg, scratch reg("rdx")] -> {
x86_64_mov_reg_imm_size(inst, $3, $2, 4);
x86_64_cdq(inst);
x86_64_idiv_reg_size(inst, $3, 4);
}
[reg("rax"), dreg, scratch reg("rdx")] -> {
jit_int min_int = jit_min_int;
unsigned char *patch, *patch2;
#ifndef JIT_USE_SIGNALS
x86_64_test_reg_reg_size(inst, $2, $2, 4);
patch = inst;
x86_branch8(inst, X86_CC_NE, 0, 0);
inst = throw_builtin(inst, func, JIT_RESULT_DIVISION_BY_ZERO);
x86_patch(patch, inst);
#endif
x86_64_cmp_reg_imm_size(inst, $2, -1, 4);
patch = inst;
x86_branch8(inst, X86_CC_NE, 0, 0);
x86_64_cmp_reg_imm_size(inst, $1, min_int, 4);
patch2 = inst;
x86_branch8(inst, X86_CC_NE, 0, 0);
inst = throw_builtin(inst, func, JIT_RESULT_ARITHMETIC);
x86_patch(patch, inst);
x86_patch(patch2, inst);
x86_64_cdq(inst);
x86_64_idiv_reg_size(inst, $2, 4);
}
JIT_OP_IDIV_UN: more_space
[any, immzero] -> {
inst = throw_builtin(inst, func, JIT_RESULT_DIVISION_BY_ZERO);
}
[reg, imm, if("$2 == 1")] -> {
}
[reg, imm, if("(((jit_nuint)$2) & (((jit_nuint)$2) - 1)) == 0")] -> {
/* x & (x - 1) is equal to zero if x is a power of 2 */
jit_nuint shift, value = $2 >> 1;
for(shift = 0; value; value >>= 1)
{
++shift;
}
x86_64_shr_reg_imm_size(inst, $1, shift, 4);
}
[reg("rax"), imm, scratch dreg, scratch reg("rdx")] -> {
x86_64_mov_reg_imm_size(inst, $3, $2, 4);
x86_64_clear_reg(inst, X86_64_RDX);
x86_64_div_reg_size(inst, $3, 4);
}
[reg("rax"), dreg, scratch reg("rdx")] -> {
#ifndef JIT_USE_SIGNALS
unsigned char *patch;
x86_64_test_reg_reg_size(inst, $2, $2, 4);
patch = inst;
x86_branch8(inst, X86_CC_NE, 0, 0);
inst = throw_builtin(inst, func, JIT_RESULT_DIVISION_BY_ZERO);
x86_patch(patch, inst);
#endif
x86_64_clear_reg(inst, X86_64_RDX);
x86_64_div_reg_size(inst, $2, 4);
}
JIT_OP_IREM: more_space
[any, immzero] -> {
inst = throw_builtin(inst, func, JIT_RESULT_DIVISION_BY_ZERO);
}
[reg, imm, if("$2 == 1")] -> {
x86_64_clear_reg(inst, $1);
}
[reg, imm, if("$2 == -1")] -> {
/* Dividing by -1 gives an exception if the argument
is minint, or simply gives a remainder of zero */
jit_int min_int = jit_min_int;
unsigned char *patch;
x86_64_cmp_reg_imm_size(inst, $1, min_int, 4);
patch = inst;
x86_branch8(inst, X86_CC_NE, 0, 0);
inst = throw_builtin(inst, func, JIT_RESULT_ARITHMETIC);
x86_patch(patch, inst);
x86_64_clear_reg(inst, $1);
}
[=reg("rdx"), *reg("rax"), imm, scratch dreg, scratch reg("rdx")] -> {
x86_64_mov_reg_imm_size(inst, $4, $3, 4);
x86_64_cdq(inst);
x86_64_idiv_reg_size(inst, $4, 4);
}
[=reg("rdx"), *reg("rax"), dreg, scratch reg("rdx")] -> {
jit_int min_int = jit_min_int;
unsigned char *patch, *patch2;
#ifndef JIT_USE_SIGNALS
x86_64_test_reg_reg_size(inst, $3, $3, 4);
patch = inst;
x86_branch8(inst, X86_CC_NE, 0, 0);
inst = throw_builtin(inst, func, JIT_RESULT_DIVISION_BY_ZERO);
x86_patch(patch, inst);
#endif
x86_64_cmp_reg_imm_size(inst, $3, -1, 4);
patch = inst;
x86_branch8(inst, X86_CC_NE, 0, 0);
x86_64_cmp_reg_imm_size(inst, $2, min_int, 4);
patch2 = inst;
x86_branch8(inst, X86_CC_NE, 0, 0);
inst = throw_builtin(inst, func, JIT_RESULT_ARITHMETIC);
x86_patch(patch, inst);
x86_patch(patch2, inst);
x86_64_cdq(inst);
x86_64_idiv_reg_size(inst, $3, 4);
}
JIT_OP_IREM_UN: more_space
[any, immzero] -> {
inst = throw_builtin(inst, func, JIT_RESULT_DIVISION_BY_ZERO);
}
[reg, imm, if("$2 == 1")] -> {
x86_64_clear_reg(inst, $1);
}
[reg, imm, if("($2 & ($2 - 1)) == 0")] -> {
/* x & (x - 1) is equal to zero if x is a power of 2 */
x86_64_and_reg_imm_size(inst, $1, $2 - 1, 4);
}
[=reg("rdx"), *reg("rax"), imm, scratch dreg, scratch reg("rdx")] -> {
x86_64_mov_reg_imm_size(inst, $4, $3, 4);
x86_64_clear_reg(inst, X86_64_RDX);
x86_64_div_reg_size(inst, $4, 4);
}
[=reg("rdx"), *reg("rax"), dreg, scratch reg("rdx")] -> {
#ifndef JIT_USE_SIGNALS
unsigned char *patch;
x86_64_test_reg_reg_size(inst, $3, $3, 4);
patch = inst;
x86_branch8(inst, X86_CC_NE, 0, 0);
inst = throw_builtin(inst, func, JIT_RESULT_DIVISION_BY_ZERO);
x86_patch(patch, inst);
#endif
x86_64_clear_reg(inst, X86_64_RDX);
x86_64_div_reg_size(inst, $3, 4);
}
/*
* 8 byte integer versions
*/
JIT_OP_LADD: commutative
[reg, imms32] -> {
if($2 == 1)
{
x86_64_inc_reg_size(inst, $1, 8);
}
else
{
x86_64_add_reg_imm_size(inst, $1, $2, 8);
}
}
[reg, local] -> {
x86_64_add_reg_membase_size(inst, $1, X86_64_RBP, $2, 8);
}
[reg, reg] -> {
x86_64_add_reg_reg_size(inst, $1, $2, 8);
}
JIT_OP_LSUB:
[reg, imms32] -> {
if($2 == 1)
{
x86_64_dec_reg_size(inst, $1, 8);
}
else
{
x86_64_sub_reg_imm_size(inst, $1, $2, 8);
}
}
[reg, local] -> {
x86_64_sub_reg_membase_size(inst, $1, X86_64_RBP, $2, 8);
}
[reg, reg] -> {
x86_64_sub_reg_reg_size(inst, $1, $2, 8);
}
JIT_OP_LNEG:
[reg] -> {
x86_64_neg_reg_size(inst, $1, 8);
}
JIT_OP_LMUL: commutative
[reg, immzero] -> {
x86_64_clear_reg(inst, $1);
}
[reg, imm, if("$2 == -1")] -> {
x86_64_neg_reg_size(inst, $1, 8);
}
[reg, imm, if("$2 == 1")] -> {
}
[reg, imm, if("$2 == 2")] -> {
x86_64_add_reg_reg_size(inst, $1, $1, 8);
}
[reg, imm, if("(((jit_nuint)$2) & (((jit_nuint)$2) - 1)) == 0")] -> {
/* x & (x - 1) is equal to zero if x is a power of 2 */
jit_nuint shift, value = $2 >> 1;
for(shift = 0; value; value >>= 1)
{
++shift;
}
x86_64_shl_reg_imm_size(inst, $1, shift, 8);
}
[reg, imms32] -> {
x86_64_imul_reg_reg_imm_size(inst, $1, $1, $2, 8);
}
[reg, local] -> {
x86_64_imul_reg_membase_size(inst, $1, X86_64_RBP, $2, 8);
}
[reg, reg] -> {
x86_64_imul_reg_reg_size(inst, $1, $2, 8);
}
JIT_OP_LDIV: more_space
[any, immzero] -> {
inst = throw_builtin(inst, func, JIT_RESULT_DIVISION_BY_ZERO);
}
[reg, imm, if("$2 == 1")] -> {
}
[reg, imm, scratch reg, if("$2 == -1")] -> {
/* Dividing by -1 gives an exception if the argument
is minint, or simply negates for other values */
jit_long min_long = jit_min_long;
unsigned char *patch;
x86_64_mov_reg_imm_size(inst, $3, min_long, 8);
x86_64_cmp_reg_reg_size(inst, $1, $3, 8);
patch = inst;
x86_branch8(inst, X86_CC_NE, 0, 0);
inst = throw_builtin(inst, func, JIT_RESULT_ARITHMETIC);
x86_patch(patch, inst);
x86_64_neg_reg_size(inst, $1, 8);
}
[reg, imm, scratch reg, if("$2 == 2")] -> {
/* move the value to be divided to the temporary */
x86_64_mov_reg_reg_size(inst, $3, $1, 8);
/* shift the temporary to the 63 bits right */
/* The result is 1 for negative values and 0 for zero or */
/* positive values. (corrective value for negatives) */
x86_64_shr_reg_imm_size(inst, $3, 0x3f, 8);
/* Add the corrective value to the divident */
x86_64_add_reg_reg_size(inst, $1, $3, 8);
/* and do the right shift */
x86_64_sar_reg_imm_size(inst, $1, 1, 8);
}
[reg, imm, scratch reg, if("($2 > 0) && (((jit_nuint)$2) & (((jit_nuint)$2) - 1)) == 0")] -> {
/* x & (x - 1) is equal to zero if x is a power of 2 */
jit_nuint shift, value = $2 >> 1;
for(shift = 0; value; value >>= 1)
{
++shift;
}
if((jit_nuint)$2 <= (jit_nuint)jit_max_uint)
{
jit_nuint corr = ($2 - 1);
x86_64_lea_membase_size(inst, $3, $1, corr, 8);
x86_64_test_reg_reg_size(inst, $1, $1, 8);
}
else
{
jit_nuint corr = ($2 - 1);
if(corr <= (jit_nuint)jit_max_uint)
{
x86_64_mov_reg_imm_size(inst, $3, corr, 4);
}
else
{
x86_64_mov_reg_imm_size(inst, $3, corr, 8);
}
x86_64_test_reg_reg_size(inst, $1, $1, 8);
x86_64_lea_memindex_size(inst, $3, $1, 0, $3, 0, 8);
}
x86_64_cmov_reg_reg_size(inst, X86_CC_S, $1, $3, 1, 8);
x86_64_sar_reg_imm_size(inst, $1, shift, 8);
}
[reg("rax"), imm, scratch dreg, scratch reg("rdx")] -> {
x86_64_mov_reg_imm_size(inst, $3, $2, 8);
x86_64_cqo(inst);
x86_64_idiv_reg_size(inst, $3, 8);
}
[reg("rax"), dreg, scratch reg("rdx")] -> {
jit_long min_long = jit_min_long;
unsigned char *patch, *patch2;
#ifndef JIT_USE_SIGNALS
x86_64_or_reg_reg_size(inst, $2, $2, 8);
patch = inst;
x86_branch8(inst, X86_CC_NE, 0, 0);
inst = throw_builtin(inst, func, JIT_RESULT_DIVISION_BY_ZERO);
x86_patch(patch, inst);
#endif
x86_64_cmp_reg_imm_size(inst, $2, -1, 8);
patch = inst;
x86_branch8(inst, X86_CC_NE, 0, 0);
x86_64_mov_reg_imm_size(inst, $3, min_long, 8);
x86_64_cmp_reg_reg_size(inst, $1, $3, 8);
patch2 = inst;
x86_branch8(inst, X86_CC_NE, 0, 0);
inst = throw_builtin(inst, func, JIT_RESULT_ARITHMETIC);
x86_patch(patch, inst);
x86_patch(patch2, inst);
x86_64_cqo(inst);
x86_64_idiv_reg_size(inst, $2, 8);
}
JIT_OP_LDIV_UN: more_space
[any, immzero] -> {
inst = throw_builtin(inst, func, JIT_RESULT_DIVISION_BY_ZERO);
}
[reg, imm, if("$2 == 1")] -> {
}
[reg, imm, if("(((jit_nuint)$2) & (((jit_nuint)$2) - 1)) == 0")] -> {
/* x & (x - 1) is equal to zero if x is a power of 2 */
jit_nuint shift, value = $2 >> 1;
for(shift = 0; value; value >>= 1)
{
++shift;
}
x86_64_shr_reg_imm_size(inst, $1, shift, 8);
}
[reg("rax"), imm, scratch dreg, scratch reg("rdx")] -> {
x86_64_mov_reg_imm_size(inst, $3, $2, 8);
x86_64_clear_reg(inst, X86_64_RDX);
x86_64_div_reg_size(inst, $3, 8);
}
[reg("rax"), dreg, scratch reg("rdx")] -> {
#ifndef JIT_USE_SIGNALS
unsigned char *patch;
x86_64_test_reg_reg_size(inst, $2, $2, 8);
patch = inst;
x86_branch8(inst, X86_CC_NE, 0, 0);
inst = throw_builtin(inst, func, JIT_RESULT_DIVISION_BY_ZERO);
x86_patch(patch, inst);
#endif
x86_64_clear_reg(inst, X86_64_RDX);
x86_64_div_reg_size(inst, $2, 8);
}
JIT_OP_LREM: more_space
[any, immzero] -> {
inst = throw_builtin(inst, func, JIT_RESULT_DIVISION_BY_ZERO);
}
[reg, imm, if("$2 == 1")] -> {
x86_64_clear_reg(inst, $1);
}
[reg, imm, if("$2 == -1")] -> {
/* Dividing by -1 gives an exception if the argument
is minint, or simply gives a remainder of zero */
jit_long min_long = jit_min_long;
unsigned char *patch;
x86_64_cmp_reg_imm_size(inst, $1, min_long, 8);
patch = inst;
x86_branch8(inst, X86_CC_NE, 0, 0);
inst = throw_builtin(inst, func, JIT_RESULT_ARITHMETIC);
x86_patch(patch, inst);
x86_64_clear_reg(inst, $1);
}
[=reg("rdx"), *reg("rax"), imm, scratch dreg, scratch reg("rdx")] -> {
x86_64_mov_reg_imm_size(inst, $4, $3, 8);
x86_64_cqo(inst);
x86_64_idiv_reg_size(inst, $4, 8);
}
[=reg("rdx"), *reg("rax"), dreg, scratch reg("rdx")] -> {
jit_long min_long = jit_min_long;
unsigned char *patch, *patch2;
#ifndef JIT_USE_SIGNALS
x86_64_test_reg_reg_size(inst, $3, $3, 8);
patch = inst;
x86_branch8(inst, X86_CC_NE, 0, 0);
inst = throw_builtin(inst, func, JIT_RESULT_DIVISION_BY_ZERO);
x86_patch(patch, inst);
#endif
x86_64_mov_reg_imm_size(inst, $1, min_long, 8);
x86_64_cmp_reg_imm_size(inst, $3, -1, 8);
patch = inst;
x86_branch8(inst, X86_CC_NE, 0, 0);
x86_64_cmp_reg_reg_size(inst, $2, $1, 8);
patch2 = inst;
x86_branch8(inst, X86_CC_NE, 0, 0);
inst = throw_builtin(inst, func, JIT_RESULT_ARITHMETIC);
x86_patch(patch, inst);
x86_patch(patch2, inst);
x86_64_cqo(inst);
x86_64_idiv_reg_size(inst, $3, 8);
}
JIT_OP_LREM_UN: more_space
[any, immzero] -> {
inst = throw_builtin(inst, func, JIT_RESULT_DIVISION_BY_ZERO);
}
[reg, imm, if("$2 == 1")] -> {
x86_64_clear_reg(inst, $1);
}
[reg, imm, scratch reg, if("(((jit_nuint)$2) & (((jit_nuint)$2) - 1)) == 0")] -> {
/* x & (x - 1) is equal to zero if x is a power of 2 */
if(($2 >= jit_min_int) && ($2 <= jit_max_int))
{
x86_64_and_reg_imm_size(inst, $1, $2 - 1, 8);
}
else
{
jit_long temp = $2 - 1;
x86_64_mov_reg_imm_size(inst, $3, temp, 8);
x86_64_and_reg_reg_size(inst, $1, $3, 8);
}
}
[=reg("rdx"), *reg("rax"), imm, scratch dreg, scratch reg("rdx")] -> {
x86_64_mov_reg_imm_size(inst, $4, $3, 8);
x86_64_clear_reg(inst, X86_64_RDX);
x86_64_div_reg_size(inst, $4, 8);
}
[=reg("rdx"), *reg("rax"), dreg, scratch reg("rdx")] -> {
#ifndef JIT_USE_SIGNALS
unsigned char *patch;
x86_64_test_reg_reg_size(inst, $3, $3, 8);
patch = inst;
x86_branch8(inst, X86_CC_NE, 0, 0);
inst = throw_builtin(inst, func, JIT_RESULT_DIVISION_BY_ZERO);
x86_patch(patch, inst);
#endif
x86_64_clear_reg(inst, X86_64_RDX);
x86_64_div_reg_size(inst, $3, 8);
}
/*
* single precision float versions
*/
JIT_OP_FADD: commutative
[xreg, imm] -> {
_jit_xmm1_reg_imm_size_float32(gen, &inst, XMM1_ADD, $1, (jit_float32 *)$2);
}
[xreg, local] -> {
x86_64_addss_reg_membase(inst, $1, X86_64_RBP, $2);
}
[xreg, xreg] -> {
x86_64_addss_reg_reg(inst, $1, $2);
}
JIT_OP_FSUB:
[xreg, imm] -> {
_jit_xmm1_reg_imm_size_float32(gen, &inst, XMM1_SUB, $1, (jit_float32 *)$2);
}
[xreg, xreg] -> {
x86_64_subss_reg_reg(inst, $1, $2);
}
[xreg, local] -> {
x86_64_subss_reg_membase(inst, $1, X86_64_RBP, $2);
}
JIT_OP_FMUL: commutative
[xreg, imm] -> {
_jit_xmm1_reg_imm_size_float32(gen, &inst, XMM1_MUL, $1, (jit_float32 *)$2);
}
[xreg, xreg] -> {
x86_64_mulss_reg_reg(inst, $1, $2);
}
[xreg, local] -> {
x86_64_mulss_reg_membase(inst, $1, X86_64_RBP, $2);
}
JIT_OP_FDIV:
[xreg, imm] -> {
_jit_xmm1_reg_imm_size_float32(gen, &inst, XMM1_DIV, $1, (jit_float32 *)$2);
}
[xreg, xreg] -> {
x86_64_divss_reg_reg(inst, $1, $2);
}
[xreg, local] -> {
x86_64_divss_reg_membase(inst, $1, X86_64_RBP, $2);
}
JIT_OP_FABS:
[xreg] -> {
/* Simply clear the sign */
jit_uint values[4] = {0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff};
_jit_plops_reg_imm(gen, &inst, XMM_ANDP, $1, &(values[0]));
libjit/jit/jit-rules-x86-64.ins view on Meta::CPAN
JIT_OP_FFLOOR: more_space
[=xreg, local, scratch reg] -> {
inst = x86_64_rounds_reg_membase(inst, $1, $2, $3, X86_ROUND_DOWN);
}
[=xreg, xreg, scratch reg] -> {
inst = x86_64_rounds_reg_reg(inst, $1, $2, $3, X86_ROUND_DOWN);
}
JIT_OP_DFLOOR: more_space
[=xreg, local, scratch reg] -> {
inst = x86_64_roundd_reg_membase(inst, $1, $2, $3, X86_ROUND_DOWN);
}
[=xreg, xreg, scratch reg] -> {
inst = x86_64_roundd_reg_reg(inst, $1, $2, $3, X86_ROUND_DOWN);
}
JIT_OP_NFFLOOR: more_space
[freg, scratch reg] -> {
inst = x86_64_roundnf(inst, $2, X86_ROUND_DOWN);
}
JIT_OP_FCEIL: more_space
[=xreg, local, scratch reg] -> {
inst = x86_64_rounds_reg_membase(inst, $1, $2, $3, X86_ROUND_UP);
}
[=xreg, xreg, scratch reg] -> {
inst = x86_64_rounds_reg_reg(inst, $1, $2, $3, X86_ROUND_UP);
}
JIT_OP_DCEIL: more_space
[=xreg, local, scratch reg] -> {
inst = x86_64_roundd_reg_membase(inst, $1, $2, $3, X86_ROUND_UP);
}
[=xreg, xreg, scratch reg] -> {
inst = x86_64_roundd_reg_reg(inst, $1, $2, $3, X86_ROUND_UP);
}
JIT_OP_NFCEIL: more_space
[freg, scratch reg] -> {
inst = x86_64_roundnf(inst, $2, X86_ROUND_UP);
}
/*
JIT_OP_FRINT: more_space
[=xreg, local, scratch reg] -> {
inst = x86_64_rounds_reg_membase(inst, $1, $2, $3, X86_ROUND_ZERO);
}
[=xreg, xreg, scratch reg] -> {
inst = x86_64_rounds_reg_reg(inst, $1, $2, $3, X86_ROUND_ZERO);
}
*/
/*
* Pointer check opcodes.
*/
JIT_OP_CHECK_NULL: note
[reg] -> {
#if 0 && defined(JIT_USE_SIGNALS)
/* if $1 contains NULL this generates SEGV and the signal
handler will throw the exception */
x86_64_cmp_reg_membase_size(inst, $1, $1, 0, 8);
#else
unsigned char *patch;
x86_64_test_reg_reg_size(inst, $1, $1, 8);
patch = inst;
x86_branch8(inst, X86_CC_NE, 0, 0);
inst = throw_builtin(inst, func, JIT_RESULT_NULL_REFERENCE);
x86_patch(patch, inst);
#endif
}
/*
* Function calls.
*/
JIT_OP_CALL:
[] -> {
jit_function_t func = (jit_function_t)(insn->dest);
inst = x86_64_call_code(inst, (jit_nint)jit_function_to_closure(func));
}
JIT_OP_CALL_TAIL:
[] -> {
jit_function_t func = (jit_function_t)(insn->dest);
x86_64_mov_reg_reg_size(inst, X86_64_RSP, X86_64_RBP, 8);
x86_64_pop_reg_size(inst, X86_64_RBP, 8);
x86_64_jump_to_code(inst, (jit_nint)jit_function_to_closure(func));
}
JIT_OP_CALL_INDIRECT:
[] -> {
x86_64_mov_reg_imm_size(inst, X86_64_RAX, 8, 4);
x86_64_call_reg(inst, X86_64_SCRATCH);
}
JIT_OP_CALL_INDIRECT_TAIL:
[] -> {
x86_64_mov_reg_reg_size(inst, X86_64_RSP, X86_64_RBP, 8);
x86_64_pop_reg_size(inst, X86_64_RBP, 8);
x86_64_jmp_reg(inst, X86_64_SCRATCH);
}
JIT_OP_CALL_VTABLE_PTR:
[] -> {
x86_64_mov_reg_imm_size(inst, X86_64_RAX, 8, 4);
x86_64_call_reg(inst, X86_64_SCRATCH);
}
JIT_OP_CALL_VTABLE_PTR_TAIL:
[] -> {
x86_64_mov_reg_reg_size(inst, X86_64_RSP, X86_64_RBP, 8);
x86_64_pop_reg_size(inst, X86_64_RBP, 8);
x86_64_jmp_reg(inst, X86_64_SCRATCH);
}
JIT_OP_CALL_EXTERNAL:
[] -> {
inst = x86_64_call_code(inst, (jit_nint)(insn->dest));
}
JIT_OP_CALL_EXTERNAL_TAIL:
[] -> {
x86_64_mov_reg_reg_size(inst, X86_64_RSP, X86_64_RBP, 8);
x86_64_pop_reg_size(inst, X86_64_RBP, 8);
x86_64_jump_to_code(inst, (jit_nint)(insn->dest));
}
/*
* Exception handling.
*/
JIT_OP_THROW: branch
[reg] -> {
x86_64_mov_reg_reg_size(inst, X86_64_RDI, $1, 8);
if(func->builder->setjmp_value != 0)
{
jit_nint pc_offset;
/* We have a "setjmp" block in the current function,
so we must record the location of the throw first */
_jit_gen_fix_value(func->builder->setjmp_value);
pc_offset = func->builder->setjmp_value->frame_offset +
jit_jmp_catch_pc_offset;
x86_64_lea_membase_size(inst, X86_64_SCRATCH, X86_64_RIP, 0, 8);
x86_64_mov_membase_reg_size(inst, X86_64_RBP, pc_offset,
X86_64_SCRATCH, 8);
}
inst = x86_64_call_code(inst, (jit_nint)jit_exception_throw);
}
JIT_OP_RETHROW: manual
[] -> { /* Not used in native code back ends */ }
JIT_OP_LOAD_PC:
[=reg] -> {
x86_64_lea_membase_size(inst, $1, X86_64_RIP, 0, 8);
}
JIT_OP_LOAD_EXCEPTION_PC: manual
[] -> { /* Not used in native code back ends */ }
JIT_OP_ENTER_FINALLY:
[] -> {
/* The return address is on the stack */
x86_64_sub_reg_imm_size(inst, X86_64_RSP, 8, 8);
}
JIT_OP_LEAVE_FINALLY: branch
[] -> {
/* The "finally" return address is on the stack */
x86_64_add_reg_imm_size(inst, X86_64_RSP, 8, 8);
x86_64_ret(inst);
}
JIT_OP_CALL_FINALLY: branch
[] -> {
jit_block_t block;
block = jit_block_from_label(func, (jit_label_t)(insn->dest));
if(!block)
{
return;
}
if(block->address)
{
inst = x86_64_call_code(inst, (jit_nint)block->address);
}
else
{
jit_int fixup;
if(block->fixup_list)
{
fixup = _JIT_CALC_FIXUP(block->fixup_list, inst + 1);
}
else
{
fixup = 0;
}
block->fixup_list = (void *)(inst + 1);
x86_64_call_imm(inst, fixup);
}
}
JIT_OP_ADDRESS_OF_LABEL:
[=reg] -> {
jit_int *fixup;
( run in 1.139 second using v1.01-cache-2.11-cpan-d7f47b0818f )