Alien-LibJIT
view release on metacpan or search on metacpan
libjit/jit/jit-rules-arm.ins view on Meta::CPAN
[reg, imm] -> {
arm_shift_reg_imm8(inst, ARM_SHL, $1, $1, ($2 & 0x1F));
}
[reg, reg] -> {
arm_alu_reg_imm8(inst, ARM_AND, ARM_WORK, $2, 0x1F);
arm_shift_reg_reg(inst, ARM_SHL, $1, $1, ARM_WORK);
}
JIT_OP_ISHR:
[reg, imm] -> {
arm_shift_reg_imm8(inst, ARM_SAR, $1, $1, ($2 & 0x1F));
}
[reg, reg] -> {
arm_alu_reg_imm8(inst, ARM_AND, ARM_WORK, $2, 0x1F);
arm_shift_reg_reg(inst, ARM_SAR, $1, $1, ARM_WORK);
}
JIT_OP_ISHR_UN:
[reg, imm] -> {
arm_shift_reg_imm8(inst, ARM_SHR, $1, $1, ($2 & 0x1F));
}
[reg, reg] -> {
arm_alu_reg_imm8(inst, ARM_AND, ARM_WORK, $2, 0x1F);
arm_shift_reg_reg(inst, ARM_SHR, $1, $1, ARM_WORK);
}
JIT_OP_LAND:
[lreg, lreg] -> {
arm_alu_reg_reg(inst, ARM_AND, $1, $1, $2);
arm_alu_reg_reg(inst, ARM_AND, %1, %1, %2);
}
JIT_OP_LOR:
[lreg, lreg] -> {
arm_alu_reg_reg(inst, ARM_ORR, $1, $1, $2);
arm_alu_reg_reg(inst, ARM_ORR, %1, %1, %2);
}
JIT_OP_LXOR:
[lreg, lreg] -> {
arm_alu_reg_reg(inst, ARM_EOR, $1, $1, $2);
arm_alu_reg_reg(inst, ARM_EOR, %1, %1, %2);
}
JIT_OP_LNOT:
[lreg] -> {
arm_alu_reg(inst, ARM_MVN, $1, $1);
arm_alu_reg(inst, ARM_MVN, %1, %1);
}
/*
* Branch opcodes.
*/
JIT_OP_BR: branch /*spill_before*/
[] -> {
/* ARM_CC_AL == "always branch" */
output_branch(func, &inst, ARM_CC_AL, insn);
/* Flush the constant pool now, to minimize the probability that
it is accidentally flushed in the middle of a loop body */
jit_gen_save_inst_ptr(gen, inst);
flush_constants(gen, 1);
jit_gen_load_inst_ptr(gen, inst);
}
JIT_OP_BR_IFALSE: branch
[reg] -> {
arm_test_reg_imm8(inst, ARM_CMP, $1, 0);
output_branch(func, &inst, ARM_CC_EQ, insn);
}
JIT_OP_BR_ITRUE: branch
[reg] -> {
arm_test_reg_imm8(inst, ARM_CMP, $1, 0);
output_branch(func, &inst, ARM_CC_NE, insn);
}
JIT_OP_BR_IEQ: branch
[reg, immu8] -> {
arm_test_reg_imm8(inst, ARM_CMP, $1, $2);
output_branch(func, &inst, ARM_CC_EQ, insn);
}
[reg, reg] -> {
arm_test_reg_reg(inst, ARM_CMP, $1, $2);
output_branch(func, &inst, ARM_CC_EQ, insn);
}
JIT_OP_BR_INE: branch
[reg, immu8] -> {
arm_test_reg_imm8(inst, ARM_CMP, $1, $2);
output_branch(func, &inst, ARM_CC_NE, insn);
}
[reg, reg] -> {
arm_test_reg_reg(inst, ARM_CMP, $1, $2);
output_branch(func, &inst, ARM_CC_NE, insn);
}
JIT_OP_BR_ILT: branch
[reg, immu8] -> {
arm_test_reg_imm8(inst, ARM_CMP, $1, $2);
output_branch(func, &inst, ARM_CC_LT, insn);
}
[reg, reg] -> {
arm_test_reg_reg(inst, ARM_CMP, $1, $2);
output_branch(func, &inst, ARM_CC_LT, insn);
}
JIT_OP_BR_ILT_UN: branch
[reg, immu8] -> {
arm_test_reg_imm8(inst, ARM_CMP, $1, $2);
output_branch(func, &inst, ARM_CC_LT_UN, insn);
}
[reg, reg] -> {
arm_test_reg_reg(inst, ARM_CMP, $1, $2);
output_branch(func, &inst, ARM_CC_LT_UN, insn);
}
JIT_OP_BR_ILE: branch
[reg, immu8] -> {
arm_test_reg_imm8(inst, ARM_CMP, $1, $2);
libjit/jit/jit-rules-arm.ins view on Meta::CPAN
_jit_regs_spill_all(gen);
_jit_gen_fix_value(insn->value1);
jit_gen_load_inst_ptr(gen, inst);
if(insn->value1->is_constant)
{
mov_reg_imm
(gen, &inst, ARM_R0, ((int *)(insn->value1->address))[0]);
}
else
{
arm_load_membase(inst, ARM_R0, ARM_FP, insn->value1->frame_offset);
}
jump_to_epilog(gen, &inst, block);
jit_gen_save_inst_ptr(gen, inst);
}
JIT_OP_RETURN_FLOAT64, JIT_OP_RETURN_NFLOAT
(JIT_ARM_HAS_VFP): branch
[freg64, clobber("r0", "r1")] -> {
arm_mov_reg_reg_double(inst,ARM_R0,ARM_R1, $1);
jump_to_epilog(gen, &inst, block);
}
JIT_OP_RETURN_FLOAT64, JIT_OP_RETURN_NFLOAT (JIT_ARM_HAS_FPA): branch
[freg] -> {
if($1 != 0)
{
arm_alu_freg(inst, ARM_MVF, ARM_F0, $1);
}
jump_to_epilog(gen, &inst, block);
}
JIT_OP_RETURN_FLOAT64, JIT_OP_RETURN_NFLOAT (!JIT_ARM_HAS_FLOAT_REGS): manual
[] -> {
arm_inst_buf inst;
_jit_regs_spill_all(gen);
_jit_gen_fix_value(insn->value1);
jit_gen_load_inst_ptr(gen, inst);
if(insn->value1->is_constant)
{
mov_reg_imm
(gen, &inst, ARM_R0, ((int *)(insn->value1->address))[0]);
mov_reg_imm
(gen, &inst, ARM_R1, ((int *)(insn->value1->address))[1]);
}
else
{
arm_load_membase(inst, ARM_R0, ARM_FP, insn->value1->frame_offset);
arm_load_membase(inst, ARM_R1, ARM_FP,
insn->value1->frame_offset + 4);
}
jump_to_epilog(gen, &inst, block);
jit_gen_save_inst_ptr(gen, inst);
}
JIT_OP_RETURN_SMALL_STRUCT: note
[reg, imm, clobber("r0", "r1")] -> {
//$1: address of the struct to be returned
//$2: size of the struct to be returned
//Prevent the accidental overwriting of the address
int temp_reg = $1;
if(temp_reg < 3)
{
arm_mov_reg_reg(inst, ARM_WORK, temp_reg);
temp_reg = ARM_WORK;
}
//Copy the struct to the return register in a way that's appropriate to its size
switch($2)
{
case 1:
arm_load_membase_byte(inst, ARM_R0, temp_reg, 0);
break;
case 2:
arm_load_membase_ushort(inst, ARM_R0, temp_reg, 0);
break;
case 3:
arm_load_membase_ushort(inst, ARM_R0, temp_reg, 0);
arm_load_membase_byte(inst, ARM_R1, temp_reg, 2);
arm_shift_reg_imm8(inst, ARM_SHL, ARM_R1, ARM_R1, 16);
arm_alu_reg_reg(inst, ARM_ORR, ARM_R0, ARM_R0, ARM_R1);
break;
case 4:
arm_load_membase(inst, ARM_R0, temp_reg, 0);
break;
/*TODO: is this the right way to return a struct > 4 bytes?
* Or should it be returned by address? Look at the Procedure Call Standard!
*/
case 5:
arm_load_membase(inst, ARM_R0, temp_reg, 0);
arm_load_membase_byte(inst, ARM_R1, temp_reg, 4);
break;
case 6:
arm_load_membase(inst, ARM_R0, temp_reg, 0);
arm_load_membase_ushort(inst, ARM_R1, temp_reg, 4);
break;
case 7:
arm_load_membase(inst, ARM_R0, temp_reg, 0);
arm_load_membase_ushort(inst, ARM_R1, temp_reg, 4);
arm_load_membase_byte(inst, ARM_R2, temp_reg, 6);
arm_shift_reg_imm8(inst, ARM_SHL, ARM_R2, ARM_R2, 16);
arm_alu_reg_reg(inst, ARM_ORR, ARM_R1, ARM_R1, ARM_R2);
break;
case 8:
arm_load_membase(inst, ARM_R0, temp_reg, 0);
arm_load_membase(inst, ARM_R1, temp_reg, 4);
break;
}
jump_to_epilog(gen, &inst, block);
}
( run in 0.789 second using v1.01-cache-2.11-cpan-524268b4103 )