Alien-LibJIT
view release on metacpan or search on metacpan
libjit/jit/jit-rules-x86.ins view on Meta::CPAN
/*
* jit-rules-x86.ins - Instruction selector for x86.
*
* Copyright (C) 2004 Southern Storm Software, Pty Ltd.
*
* This file is part of the libjit library.
*
* The libjit library is free software: you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public License
* as published by the Free Software Foundation, either version 2.1 of
* the License, or (at your option) any later version.
*
* The libjit library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with the libjit library. If not, see
* <http://www.gnu.org/licenses/>.
*/
%regclass reg x86_reg
%regclass breg x86_breg
%regclass freg x86_freg
%lregclass lreg x86_lreg
/*
* Conversion opcodes.
*/
JIT_OP_TRUNC_SBYTE:
[=reg, breg] -> {
x86_widen_reg(inst, $1, $2, 1, 0);
}
JIT_OP_TRUNC_UBYTE:
[=reg, breg] -> {
x86_widen_reg(inst, $1, $2, 0, 0);
}
JIT_OP_TRUNC_SHORT:
[=reg, reg] -> {
x86_widen_reg(inst, $1, $2, 1, 1);
}
JIT_OP_TRUNC_USHORT:
[=reg, reg] -> {
x86_widen_reg(inst, $1, $2, 0, 1);
}
JIT_OP_CHECK_SBYTE: more_space
[reg] -> {
unsigned char *patch1;
unsigned char *patch2;
x86_alu_reg_imm(inst, X86_CMP, $1, -128);
patch1 = inst;
x86_branch8(inst, X86_CC_LE, 0, 1);
x86_alu_reg_imm(inst, X86_CMP, $1, 127);
patch2 = inst;
x86_branch8(inst, X86_CC_LE, 0, 1);
x86_patch(patch1, inst);
libjit/jit/jit-rules-x86.ins view on Meta::CPAN
x86_alu_reg_imm(inst, X86_ADD, $1, value1);
x86_alu_reg_imm(inst, X86_ADC, %1, value2);
}
else
{
x86_alu_reg_imm(inst, X86_ADD, %1, value2);
}
}
[lreg, local] -> {
x86_alu_reg_membase(inst, X86_ADD, $1, X86_EBP, $2);
x86_alu_reg_membase(inst, X86_ADC, %1, X86_EBP, $2 + 4);
}
[lreg, lreg] -> {
x86_alu_reg_reg(inst, X86_ADD, $1, $2);
x86_alu_reg_reg(inst, X86_ADC, %1, %2);
}
JIT_OP_LSUB:
[lreg, imm] -> {
jit_int value1 = ((jit_int *)($2))[0];
jit_int value2 = ((jit_int *)($2))[1];
if(value1 != 0)
{
x86_alu_reg_imm(inst, X86_SUB, $1, value1);
x86_alu_reg_imm(inst, X86_SBB, %1, value2);
}
else
{
x86_alu_reg_imm(inst, X86_SUB, %1, value2);
}
}
[lreg, local] -> {
x86_alu_reg_membase(inst, X86_SUB, $1, X86_EBP, $2);
x86_alu_reg_membase(inst, X86_SBB, %1, X86_EBP, $2 + 4);
}
[lreg, lreg] -> {
x86_alu_reg_reg(inst, X86_SUB, $1, $2);
x86_alu_reg_reg(inst, X86_SBB, %1, %2);
}
JIT_OP_LNEG:
[lreg] -> {
/* TODO: gcc generates the first variant while
AoA suggests the second. Figure out if one
is better than other. */
#if 1
x86_neg_reg(inst, $1);
x86_alu_reg_imm(inst, X86_ADC, %1, 0);
x86_neg_reg(inst, %1);
#else
x86_neg_reg(inst, %1);
x86_neg_reg(inst, $1);
x86_alu_reg_imm(inst, X86_SBB, %1, 0);
#endif
}
JIT_OP_FADD, JIT_OP_DADD, JIT_OP_NFADD: stack, x87_arith, commutative
[freg, freg] -> {
int flags;
flags = _jit_regs_select(®s);
if((flags & _JIT_REGS_NO_POP) == 0)
{
x86_fp_op_reg(inst, X86_FADD,
fp_stack_index(gen, $1 + JIT_REG_STACK_START), 1);
}
else if((flags & _JIT_REGS_FLIP_ARGS) != 0)
{
x86_fp_op_reg(inst, X86_FADD,
fp_stack_index(gen, $1 + JIT_REG_STACK_START), 0);
}
else
{
x86_fp_op(inst, X86_FADD,
fp_stack_index(gen, $2 + JIT_REG_STACK_START));
}
}
JIT_OP_FSUB, JIT_OP_DSUB, JIT_OP_NFSUB: stack, x87_arith_reversible
[freg, freg] -> {
int flags;
flags = _jit_regs_select(®s);
if((flags & _JIT_REGS_NO_POP) == 0)
{
if((flags & _JIT_REGS_REVERSE) == 0)
{
x86_fp_op_reg(inst, X86_FSUB,
fp_stack_index(gen, $1 + JIT_REG_STACK_START), 1);
}
else
{
x86_fp_op_reg(inst, X86_FSUBR,
fp_stack_index(gen, $2 + JIT_REG_STACK_START), 1);
}
}
else if((flags & _JIT_REGS_FLIP_ARGS) != 0)
{
if((flags & _JIT_REGS_REVERSE) == 0)
{
x86_fp_op_reg(inst, X86_FSUB,
fp_stack_index(gen, $1 + JIT_REG_STACK_START), 0);
}
else
{
x86_fp_op(inst, X86_FSUBR,
fp_stack_index(gen, $1 + JIT_REG_STACK_START));
}
}
else
{
if((flags & _JIT_REGS_REVERSE) == 0)
{
x86_fp_op(inst, X86_FSUB,
fp_stack_index(gen, $2 + JIT_REG_STACK_START));
}
else
{
x86_fp_op_reg(inst, X86_FSUBR,
fp_stack_index(gen, $2 + JIT_REG_STACK_START), 0);
}
}
}
JIT_OP_FMUL, JIT_OP_DMUL, JIT_OP_NFMUL: stack, x87_arith, commutative
[freg, freg] -> {
int flags;
flags = _jit_regs_select(®s);
if((flags & _JIT_REGS_NO_POP) == 0)
{
x86_fp_op_reg(inst, X86_FMUL, fp_stack_index(gen, $1 + JIT_REG_STACK_START), 1);
}
else if((flags & _JIT_REGS_FLIP_ARGS) != 0)
{
x86_fp_op_reg(inst, X86_FMUL, fp_stack_index(gen, $1 + JIT_REG_STACK_START), 0);
}
else
{
x86_fp_op(inst, X86_FMUL, fp_stack_index(gen, $2 + JIT_REG_STACK_START));
}
}
JIT_OP_FDIV, JIT_OP_DDIV, JIT_OP_NFDIV: stack, x87_arith_reversible
[freg, freg] -> {
int flags;
flags = _jit_regs_select(®s);
if((flags & _JIT_REGS_NO_POP) == 0)
{
if((flags & _JIT_REGS_REVERSE) == 0)
{
x86_fp_op_reg(inst, X86_FDIV,
fp_stack_index(gen, $1 + JIT_REG_STACK_START), 1);
}
else
{
x86_fp_op_reg(inst, X86_FDIVR,
fp_stack_index(gen, $2 + JIT_REG_STACK_START), 1);
}
}
else if((flags & _JIT_REGS_FLIP_ARGS) != 0)
{
if((flags & _JIT_REGS_REVERSE) == 0)
{
x86_fp_op_reg(inst, X86_FDIV,
fp_stack_index(gen, $1 + JIT_REG_STACK_START), 0);
}
else
{
x86_fp_op(inst, X86_FDIVR,
fp_stack_index(gen, $1 + JIT_REG_STACK_START));
}
}
else
{
if((flags & _JIT_REGS_REVERSE) == 0)
{
x86_fp_op(inst, X86_FDIV,
fp_stack_index(gen, $2 + JIT_REG_STACK_START));
}
else
{
x86_fp_op_reg(inst, X86_FDIVR,
fp_stack_index(gen, $2 + JIT_REG_STACK_START), 0);
}
}
}
JIT_OP_FREM, JIT_OP_DREM, JIT_OP_NFREM: stack
[freg, freg, scratch reg("eax")] -> {
unsigned char *label;
label = inst;
x86_fprem(inst);
x86_fnstsw(inst);
x86_alu_reg_imm(inst, X86_AND, X86_EAX, 0x0400);
x86_branch(inst, X86_CC_NZ, label, 0);
x86_fstp(inst, 1);
}
JIT_OP_FNEG, JIT_OP_DNEG, JIT_OP_NFNEG: stack
[freg] -> {
x86_fchs(inst);
}
/*
* Bitwise opcodes.
( run in 0.745 second using v1.01-cache-2.11-cpan-d0baa829c65 )