You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

1401 lines
33 KiB

/*
* jit-rules-arm.sel - Instruction selector for ARM.
*
* Copyright (C) 2004 Southern Storm Software, Pty Ltd.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
%inst_type arm_inst_buf
/*
* Conversion opcodes.
*/
JIT_OP_TRUNC_SBYTE: unary
[reg] -> {
arm_shift_reg_imm8(inst, ARM_SHL, $1, $1, 24);
arm_shift_reg_imm8(inst, ARM_SAR, $1, $1, 24);
}
JIT_OP_TRUNC_UBYTE: unary
[reg] -> {
arm_alu_reg_imm8(inst, ARM_AND, $1, $1, 0xFF);
}
JIT_OP_TRUNC_SHORT: unary
[reg] -> {
arm_shift_reg_imm8(inst, ARM_SHL, $1, $1, 16);
arm_shift_reg_imm8(inst, ARM_SAR, $1, $1, 16);
}
JIT_OP_TRUNC_USHORT: unary
[reg] -> {
arm_shift_reg_imm8(inst, ARM_SHL, $1, $1, 16);
arm_shift_reg_imm8(inst, ARM_SHR, $1, $1, 16);
}
/*
* Arithmetic opcodes.
*/
JIT_OP_IADD: binary
[reg, immu8] -> {
arm_alu_reg_imm8(inst, ARM_ADD, $1, $1, $2);
}
[reg, reg] -> {
arm_alu_reg_reg(inst, ARM_ADD, $1, $1, $2);
}
JIT_OP_ISUB: binary
[reg, immu8] -> {
arm_alu_reg_imm8(inst, ARM_SUB, $1, $1, $2);
}
[reg, reg] -> {
arm_alu_reg_reg(inst, ARM_SUB, $1, $1, $2);
}
JIT_OP_IMUL: binary
[reg, immu8] -> {
/* Handle special cases of immediate multiplies */
switch($2)
{
case 0:
{
arm_mov_reg_imm8(inst, $1, 0);
}
break;
case 1: break;
case 2:
{
arm_shift_reg_imm8(inst, ARM_SHL, $1, $1, 1);
}
break;
case 4:
{
arm_shift_reg_imm8(inst, ARM_SHL, $1, $1, 2);
}
break;
case 8:
{
arm_shift_reg_imm8(inst, ARM_SHL, $1, $1, 3);
}
break;
case 16:
{
arm_shift_reg_imm8(inst, ARM_SHL, $1, $1, 4);
}
break;
case 32:
{
arm_shift_reg_imm8(inst, ARM_SHL, $1, $1, 5);
}
break;
case 64:
{
arm_shift_reg_imm8(inst, ARM_SHL, $1, $1, 6);
}
break;
case 128:
{
arm_shift_reg_imm8(inst, ARM_SHL, $1, $1, 7);
}
break;
default:
{
arm_mov_reg_imm8(inst, ARM_WORK, $2);
arm_mul_reg_reg(inst, $1, $1, ARM_WORK);
}
break;
}
}
[reg, reg] -> {
if($1 != $2)
{
arm_mul_reg_reg(inst, $1, $1, $2);
}
else
{
/* Cannot use the same register for both arguments */
arm_mov_reg_reg(inst, ARM_WORK, $2);
arm_mul_reg_reg(inst, $1, $1, ARM_WORK);
}
}
JIT_OP_INEG: unary
[reg] -> {
/* -x is the same as (0 - x) */
arm_alu_reg_imm8(inst, ARM_RSB, $1, $1, 0);
}
JIT_OP_LADD: binary
[lreg, lreg] -> {
arm_alu_cc_reg_reg(inst, ARM_ADD, $1, $1, $2);
arm_alu_reg_reg(inst, ARM_ADC, %1, %1, %2);
}
JIT_OP_LSUB: binary
[lreg, lreg] -> {
arm_alu_cc_reg_reg(inst, ARM_SUB, $1, $1, $2);
arm_alu_reg_reg(inst, ARM_SBC, %1, %1, %2);
}
JIT_OP_LNEG: unary
[lreg] -> {
arm_alu_reg(inst, ARM_MVN, $1, $1);
arm_alu_reg(inst, ARM_MVN, %1, %1);
arm_alu_cc_reg_imm8(inst, ARM_ADD, $1, $1, 1);
arm_alu_reg_imm8(inst, ARM_ADC, %1, %1, 0);
}
JIT_OP_FADD (JIT_ARM_HAS_FLOAT_REGS): binary
[freg, freg] -> {
arm_alu_freg_freg_32(inst, ARM_ADF, $1, $1, $2);
}
JIT_OP_FSUB (JIT_ARM_HAS_FLOAT_REGS): binary
[freg, freg] -> {
arm_alu_freg_freg_32(inst, ARM_SUF, $1, $1, $2);
}
JIT_OP_FMUL (JIT_ARM_HAS_FLOAT_REGS): binary
[freg, freg] -> {
arm_alu_freg_freg_32(inst, ARM_MUF, $1, $1, $2);
}
JIT_OP_FDIV (JIT_ARM_HAS_FLOAT_REGS): binary
[freg, freg] -> {
arm_alu_freg_freg_32(inst, ARM_DVF, $1, $1, $2);
}
JIT_OP_FNEG (JIT_ARM_HAS_FLOAT_REGS): unary
[freg] -> {
arm_alu_freg_32(inst, ARM_MNF, $1, $1);
}
JIT_OP_DADD, JIT_OP_NFADD (JIT_ARM_HAS_FLOAT_REGS): binary
[freg, freg] -> {
arm_alu_freg_freg(inst, ARM_ADF, $1, $1, $2);
}
JIT_OP_DSUB, JIT_OP_NFSUB (JIT_ARM_HAS_FLOAT_REGS): binary
[freg, freg] -> {
arm_alu_freg_freg(inst, ARM_SUF, $1, $1, $2);
}
JIT_OP_DMUL, JIT_OP_NFMUL (JIT_ARM_HAS_FLOAT_REGS): binary
[freg, freg] -> {
arm_alu_freg_freg(inst, ARM_MUF, $1, $1, $2);
}
JIT_OP_DDIV, JIT_OP_NFDIV (JIT_ARM_HAS_FLOAT_REGS): binary
[freg, freg] -> {
arm_alu_freg_freg(inst, ARM_DVF, $1, $1, $2);
}
JIT_OP_DNEG, JIT_OP_NFNEG (JIT_ARM_HAS_FLOAT_REGS): unary
[freg] -> {
arm_alu_freg(inst, ARM_MNF, $1, $1);
}
/*
* Bitwise opcodes.
*/
JIT_OP_IAND: binary
[reg, immu8] -> {
arm_alu_reg_imm8(inst, ARM_AND, $1, $1, $2);
}
[reg, reg] -> {
arm_alu_reg_reg(inst, ARM_AND, $1, $1, $2);
}
JIT_OP_IOR: binary
[reg, immu8] -> {
arm_alu_reg_imm8(inst, ARM_ORR, $1, $1, $2);
}
[reg, reg] -> {
arm_alu_reg_reg(inst, ARM_ORR, $1, $1, $2);
}
JIT_OP_IXOR: binary
[reg, immu8] -> {
arm_alu_reg_imm8(inst, ARM_EOR, $1, $1, $2);
}
[reg, reg] -> {
arm_alu_reg_reg(inst, ARM_EOR, $1, $1, $2);
}
JIT_OP_INOT: unary
[reg] -> {
/* MVN == "move not" */
arm_alu_reg(inst, ARM_MVN, $1, $1);
}
JIT_OP_ISHL: binary
[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: binary
[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: binary
[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: binary
[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: binary
[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: binary
[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: unary
[lreg] -> {
arm_alu_reg(inst, ARM_MVN, $1, $1);
arm_alu_reg(inst, ARM_MVN, %1, %1);
}
/*
* Branch opcodes.
*/
JIT_OP_BR: 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: unary_branch
[reg] -> {
arm_test_reg_imm8(inst, ARM_CMP, $1, 0);
output_branch(func, &inst, ARM_CC_EQ, insn);
}
JIT_OP_BR_ITRUE: unary_branch
[reg] -> {
arm_test_reg_imm8(inst, ARM_CMP, $1, 0);
output_branch(func, &inst, ARM_CC_NE, insn);
}
JIT_OP_BR_IEQ: binary_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: binary_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: binary_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: binary_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: binary_branch
[reg, immu8] -> {
arm_test_reg_imm8(inst, ARM_CMP, $1, $2);
output_branch(func, &inst, ARM_CC_LE, insn);
}
[reg, reg] -> {
arm_test_reg_reg(inst, ARM_CMP, $1, $2);
output_branch(func, &inst, ARM_CC_LE, insn);
}
JIT_OP_BR_ILE_UN: binary_branch
[reg, immu8] -> {
arm_test_reg_imm8(inst, ARM_CMP, $1, $2);
output_branch(func, &inst, ARM_CC_LE_UN, insn);
}
[reg, reg] -> {
arm_test_reg_reg(inst, ARM_CMP, $1, $2);
output_branch(func, &inst, ARM_CC_LE_UN, insn);
}
JIT_OP_BR_IGT: binary_branch
[reg, immu8] -> {
arm_test_reg_imm8(inst, ARM_CMP, $1, $2);
output_branch(func, &inst, ARM_CC_GT, insn);
}
[reg, reg] -> {
arm_test_reg_reg(inst, ARM_CMP, $1, $2);
output_branch(func, &inst, ARM_CC_GT, insn);
}
JIT_OP_BR_IGT_UN: binary_branch
[reg, immu8] -> {
arm_test_reg_imm8(inst, ARM_CMP, $1, $2);
output_branch(func, &inst, ARM_CC_GT_UN, insn);
}
[reg, reg] -> {
arm_test_reg_reg(inst, ARM_CMP, $1, $2);
output_branch(func, &inst, ARM_CC_GT_UN, insn);
}
JIT_OP_BR_IGE: binary_branch
[reg, immu8] -> {
arm_test_reg_imm8(inst, ARM_CMP, $1, $2);
output_branch(func, &inst, ARM_CC_GE, insn);
}
[reg, reg] -> {
arm_test_reg_reg(inst, ARM_CMP, $1, $2);
output_branch(func, &inst, ARM_CC_GE, insn);
}
JIT_OP_BR_IGE_UN: binary_branch
[reg, immu8] -> {
arm_test_reg_imm8(inst, ARM_CMP, $1, $2);
output_branch(func, &inst, ARM_CC_GE_UN, insn);
}
[reg, reg] -> {
arm_test_reg_reg(inst, ARM_CMP, $1, $2);
output_branch(func, &inst, ARM_CC_GE_UN, insn);
}
/*
* Comparison opcodes.
*/
JIT_OP_ICMP: binary
[reg, immu8] -> {
arm_test_reg_imm8(inst, ARM_CMP, $1, $2);
arm_alu_reg_imm8_cond(inst, ARM_MOV, $1, 0, 1, ARM_CC_GT);
arm_alu_reg_imm8_cond(inst, ARM_MOV, $1, 0, 0, ARM_CC_LE);
arm_alu_reg_cond(inst, ARM_MVN, $1, $1, ARM_CC_LT);
}
[reg, reg] -> {
arm_test_reg_reg(inst, ARM_CMP, $1, $2);
arm_alu_reg_imm8_cond(inst, ARM_MOV, $1, 0, 1, ARM_CC_GT);
arm_alu_reg_imm8_cond(inst, ARM_MOV, $1, 0, 0, ARM_CC_LE);
arm_alu_reg_cond(inst, ARM_MVN, $1, $1, ARM_CC_LT);
}
JIT_OP_ICMP_UN: binary
[reg, immu8] -> {
arm_test_reg_imm8(inst, ARM_CMP, $1, $2);
arm_alu_reg_imm8_cond(inst, ARM_MOV, $1, 0, 1, ARM_CC_GT_UN);
arm_alu_reg_imm8_cond(inst, ARM_MOV, $1, 0, 0, ARM_CC_LE_UN);
arm_alu_reg_cond(inst, ARM_MVN, $1, $1, ARM_CC_LT_UN);
}
[reg, reg] -> {
arm_test_reg_reg(inst, ARM_CMP, $1, $2);
arm_alu_reg_imm8_cond(inst, ARM_MOV, $1, 0, 1, ARM_CC_GT_UN);
arm_alu_reg_imm8_cond(inst, ARM_MOV, $1, 0, 0, ARM_CC_LE_UN);
arm_alu_reg_cond(inst, ARM_MVN, $1, $1, ARM_CC_LT_UN);
}
JIT_OP_IEQ: binary
[reg, immu8] -> {
arm_test_reg_imm8(inst, ARM_CMP, $1, $2);
arm_alu_reg_imm8_cond(inst, ARM_MOV, $1, 0, 1, ARM_CC_EQ);
arm_alu_reg_imm8_cond(inst, ARM_MOV, $1, 0, 0, ARM_CC_NE);
}
[reg, reg] -> {
arm_test_reg_reg(inst, ARM_CMP, $1, $2);
arm_alu_reg_imm8_cond(inst, ARM_MOV, $1, 0, 1, ARM_CC_EQ);
arm_alu_reg_imm8_cond(inst, ARM_MOV, $1, 0, 0, ARM_CC_NE);
}
JIT_OP_INE: binary
[reg, immu8] -> {
arm_test_reg_imm8(inst, ARM_CMP, $1, $2);
arm_alu_reg_imm8_cond(inst, ARM_MOV, $1, 0, 1, ARM_CC_NE);
arm_alu_reg_imm8_cond(inst, ARM_MOV, $1, 0, 0, ARM_CC_EQ);
}
[reg, reg] -> {
arm_test_reg_reg(inst, ARM_CMP, $1, $2);
arm_alu_reg_imm8_cond(inst, ARM_MOV, $1, 0, 1, ARM_CC_NE);
arm_alu_reg_imm8_cond(inst, ARM_MOV, $1, 0, 0, ARM_CC_EQ);
}
JIT_OP_ILT: binary
[reg, immu8] -> {
arm_test_reg_imm8(inst, ARM_CMP, $1, $2);
arm_alu_reg_imm8_cond(inst, ARM_MOV, $1, 0, 1, ARM_CC_LT);
arm_alu_reg_imm8_cond(inst, ARM_MOV, $1, 0, 0, ARM_CC_GE);
}
[reg, reg] -> {
arm_test_reg_reg(inst, ARM_CMP, $1, $2);
arm_alu_reg_imm8_cond(inst, ARM_MOV, $1, 0, 1, ARM_CC_LT);
arm_alu_reg_imm8_cond(inst, ARM_MOV, $1, 0, 0, ARM_CC_GE);
}
JIT_OP_ILT_UN: binary
[reg, immu8] -> {
arm_test_reg_imm8(inst, ARM_CMP, $1, $2);
arm_alu_reg_imm8_cond(inst, ARM_MOV, $1, 0, 1, ARM_CC_LT_UN);
arm_alu_reg_imm8_cond(inst, ARM_MOV, $1, 0, 0, ARM_CC_GE_UN);
}
[reg, reg] -> {
arm_test_reg_reg(inst, ARM_CMP, $1, $2);
arm_alu_reg_imm8_cond(inst, ARM_MOV, $1, 0, 1, ARM_CC_LT_UN);
arm_alu_reg_imm8_cond(inst, ARM_MOV, $1, 0, 0, ARM_CC_GE_UN);
}
JIT_OP_ILE: binary
[reg, immu8] -> {
arm_test_reg_imm8(inst, ARM_CMP, $1, $2);
arm_alu_reg_imm8_cond(inst, ARM_MOV, $1, 0, 1, ARM_CC_LE);
arm_alu_reg_imm8_cond(inst, ARM_MOV, $1, 0, 0, ARM_CC_GT);
}
[reg, reg] -> {
arm_test_reg_reg(inst, ARM_CMP, $1, $2);
arm_alu_reg_imm8_cond(inst, ARM_MOV, $1, 0, 1, ARM_CC_LE);
arm_alu_reg_imm8_cond(inst, ARM_MOV, $1, 0, 0, ARM_CC_GT);
}
JIT_OP_ILE_UN: binary
[reg, immu8] -> {
arm_test_reg_imm8(inst, ARM_CMP, $1, $2);
arm_alu_reg_imm8_cond(inst, ARM_MOV, $1, 0, 1, ARM_CC_LE_UN);
arm_alu_reg_imm8_cond(inst, ARM_MOV, $1, 0, 0, ARM_CC_GT_UN);
}
[reg, reg] -> {
arm_test_reg_reg(inst, ARM_CMP, $1, $2);
arm_alu_reg_imm8_cond(inst, ARM_MOV, $1, 0, 1, ARM_CC_LE_UN);
arm_alu_reg_imm8_cond(inst, ARM_MOV, $1, 0, 0, ARM_CC_GT_UN);
}
JIT_OP_IGT: binary
[reg, immu8] -> {
arm_test_reg_imm8(inst, ARM_CMP, $1, $2);
arm_alu_reg_imm8_cond(inst, ARM_MOV, $1, 0, 1, ARM_CC_GT);
arm_alu_reg_imm8_cond(inst, ARM_MOV, $1, 0, 0, ARM_CC_LE);
}
[reg, reg] -> {
arm_test_reg_reg(inst, ARM_CMP, $1, $2);
arm_alu_reg_imm8_cond(inst, ARM_MOV, $1, 0, 1, ARM_CC_GT);
arm_alu_reg_imm8_cond(inst, ARM_MOV, $1, 0, 0, ARM_CC_LE);
}
JIT_OP_IGT_UN: binary
[reg, immu8] -> {
arm_test_reg_imm8(inst, ARM_CMP, $1, $2);
arm_alu_reg_imm8_cond(inst, ARM_MOV, $1, 0, 1, ARM_CC_GT_UN);
arm_alu_reg_imm8_cond(inst, ARM_MOV, $1, 0, 0, ARM_CC_LE_UN);
}
[reg, reg] -> {
arm_test_reg_reg(inst, ARM_CMP, $1, $2);
arm_alu_reg_imm8_cond(inst, ARM_MOV, $1, 0, 1, ARM_CC_GT_UN);
arm_alu_reg_imm8_cond(inst, ARM_MOV, $1, 0, 0, ARM_CC_LE_UN);
}
JIT_OP_IGE: binary
[reg, immu8] -> {
arm_test_reg_imm8(inst, ARM_CMP, $1, $2);
arm_alu_reg_imm8_cond(inst, ARM_MOV, $1, 0, 1, ARM_CC_GE);
arm_alu_reg_imm8_cond(inst, ARM_MOV, $1, 0, 0, ARM_CC_LT);
}
[reg, reg] -> {
arm_test_reg_reg(inst, ARM_CMP, $1, $2);
arm_alu_reg_imm8_cond(inst, ARM_MOV, $1, 0, 1, ARM_CC_GE);
arm_alu_reg_imm8_cond(inst, ARM_MOV, $1, 0, 0, ARM_CC_LT);
}
JIT_OP_IGE_UN: binary
[reg, immu8] -> {
arm_test_reg_imm8(inst, ARM_CMP, $1, $2);
arm_alu_reg_imm8_cond(inst, ARM_MOV, $1, 0, 1, ARM_CC_GE_UN);
arm_alu_reg_imm8_cond(inst, ARM_MOV, $1, 0, 0, ARM_CC_LT_UN);
}
[reg, reg] -> {
arm_test_reg_reg(inst, ARM_CMP, $1, $2);
arm_alu_reg_imm8_cond(inst, ARM_MOV, $1, 0, 1, ARM_CC_GE_UN);
arm_alu_reg_imm8_cond(inst, ARM_MOV, $1, 0, 0, ARM_CC_LT_UN);
}
/*
* Pointer check opcodes.
*/
JIT_OP_CHECK_NULL: unary_note
[reg] -> {
arm_test_reg_imm8(inst, ARM_CMP, $1, 0);
throw_builtin(&inst, func, ARM_CC_EQ, JIT_RESULT_NULL_REFERENCE);
}
/*
* Function calls.
*/
JIT_OP_CALL:
[] -> {
jit_function_t func = (jit_function_t)(insn->dest);
arm_call(inst, func->closure_entry);
}
JIT_OP_CALL_TAIL:
[] -> {
jit_function_t func = (jit_function_t)(insn->dest);
arm_pop_frame_tail(inst, 0);
arm_jump(inst, func->closure_entry);
}
JIT_OP_CALL_INDIRECT:
[] -> {
arm_mov_reg_reg((inst), ARM_LINK, ARM_PC);
arm_mov_reg_reg((inst), ARM_PC, ARM_WORK);
}
JIT_OP_CALL_VTABLE_PTR:
[] -> {
arm_mov_reg_reg((inst), ARM_LINK, ARM_PC);
arm_mov_reg_reg((inst), ARM_PC, ARM_WORK);
}
JIT_OP_CALL_EXTERNAL:
[] -> {
arm_call(inst, (void *)(insn->dest));
}
JIT_OP_RETURN:
[] -> {
jump_to_epilog(gen, &inst, block);
}
JIT_OP_RETURN_INT: unary_branch
[reg] -> {
int cpu_reg = $1;
if(cpu_reg != ARM_R0)
{
arm_mov_reg_reg(inst, ARM_R0, cpu_reg);
}
jump_to_epilog(gen, &inst, block);
}
JIT_OP_RETURN_LONG: unary_branch
[imm] -> {
mov_reg_imm(gen, &inst, ARM_R0, ((jit_int *)($1))[0]);
mov_reg_imm(gen, &inst, ARM_R1, ((jit_int *)($1))[1]);
jump_to_epilog(gen, &inst, block);
}
[local] -> {
arm_load_membase(inst, ARM_R0, ARM_FP, $1);
arm_load_membase(inst, ARM_R1, ARM_FP, $1 + 4);
jump_to_epilog(gen, &inst, block);
}
[lreg] -> {
if($1 != 0)
{
arm_mov_reg_reg(inst, ARM_R0, $1);
arm_mov_reg_reg(inst, ARM_R1, %1);
}
jump_to_epilog(gen, &inst, block);
}
JIT_OP_RETURN_FLOAT32 (JIT_ARM_HAS_FLOAT_REGS): unary_branch
[freg] -> {
if($1 != 0)
{
arm_alu_freg_32(inst, ARM_MVF, ARM_F0, $1);
}
jump_to_epilog(gen, &inst, block);
}
JIT_OP_RETURN_FLOAT32 (!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]);
}
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_FLOAT_REGS): unary_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: unary_branch
[reg] -> {
int temp_reg = $1;
if(temp_reg < 3)
{
arm_mov_reg_reg(inst, ARM_WORK, temp_reg);
temp_reg = ARM_WORK;
}
switch(insn->value2->address)
{
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;
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);
}
JIT_OP_SETUP_FOR_NESTED: spill_before
[] -> {
jit_nint nest_reg = jit_value_get_nint_constant(insn->value1);
if(nest_reg == -1)
{
arm_push_reg(inst, ARM_FP);
}
else
{
arm_mov_reg_reg(inst, _jit_reg_info[nest_reg].cpu_reg, ARM_FP);
}
}
JIT_OP_SETUP_FOR_SIBLING: spill_before
[] -> {
jit_nint level = jit_value_get_nint_constant(insn->value1);
jit_nint nest_reg = jit_value_get_nint_constant(insn->value2);
int cpu_reg;
if(nest_reg == -1)
{
cpu_reg = ARM_R0;
}
else
{
cpu_reg = _jit_reg_info[nest_reg].cpu_reg;
}
arm_load_membase(inst, cpu_reg, ARM_FP, JIT_APPLY_PARENT_FRAME_OFFSET);
while(level > 0)
{
arm_load_membase(inst, cpu_reg, cpu_reg,
JIT_APPLY_PARENT_FRAME_OFFSET);
--level;
}
if(nest_reg == -1)
{
arm_push_reg(inst, cpu_reg);
}
}
JIT_OP_IMPORT:
[] -> {
/* TODO */
TODO();
}
/*
* Data manipulation.
*/
JIT_OP_COPY_LOAD_SBYTE: unary
[reg] -> {}
JIT_OP_COPY_LOAD_UBYTE: unary
[reg] -> {}
JIT_OP_COPY_LOAD_SHORT: unary
[reg] -> {}
JIT_OP_COPY_LOAD_USHORT: unary
[reg] -> {}
JIT_OP_COPY_INT: unary
[reg] -> {}
JIT_OP_COPY_LONG: unary
[lreg] -> {}
JIT_OP_COPY_FLOAT32 (JIT_ARM_HAS_FLOAT_REGS): unary
[freg] -> {}
JIT_OP_COPY_FLOAT32 (!JIT_ARM_HAS_FLOAT_REGS): manual
[] -> {
arm_inst_buf inst;
_jit_regs_force_out(gen, insn->value1, 0);
_jit_regs_force_out(gen, insn->dest, 1);
_jit_gen_fix_value(insn->value1);
_jit_gen_fix_value(insn->dest);
jit_gen_load_inst_ptr(gen, inst);
if(insn->value1->is_constant)
{
mov_reg_imm
(gen, &inst, ARM_WORK, ((int *)(insn->value1->address))[0]);
}
else
{
arm_load_membase(inst, ARM_WORK, ARM_FP,
insn->value1->frame_offset);
}
arm_store_membase(inst, ARM_WORK, ARM_FP, insn->dest->frame_offset);
jit_gen_save_inst_ptr(gen, inst);
}
JIT_OP_COPY_FLOAT64, JIT_OP_COPY_NFLOAT (JIT_ARM_HAS_FLOAT_REGS): unary
[freg] -> {}
JIT_OP_COPY_FLOAT64, JIT_OP_COPY_NFLOAT (!JIT_ARM_HAS_FLOAT_REGS): manual
[] -> {
arm_inst_buf inst;
_jit_regs_force_out(gen, insn->value1, 0);
_jit_regs_force_out(gen, insn->dest, 1);
_jit_gen_fix_value(insn->value1);
_jit_gen_fix_value(insn->dest);
jit_gen_load_inst_ptr(gen, inst);
if(insn->value1->is_constant)
{
mov_reg_imm
(gen, &inst, ARM_WORK, ((int *)(insn->value1->address))[0]);
arm_store_membase(inst, ARM_WORK, ARM_FP,
insn->dest->frame_offset);
mov_reg_imm
(gen, &inst, ARM_WORK, ((int *)(insn->value1->address))[1]);
arm_store_membase(inst, ARM_WORK, ARM_FP,
insn->dest->frame_offset + 4);
}
else
{
arm_load_membase(inst, ARM_WORK, ARM_FP,
insn->value1->frame_offset);
arm_store_membase(inst, ARM_WORK, ARM_FP,
insn->dest->frame_offset);
arm_load_membase(inst, ARM_WORK, ARM_FP,
insn->value1->frame_offset + 4);
arm_store_membase(inst, ARM_WORK, ARM_FP,
insn->dest->frame_offset + 4);
}
jit_gen_save_inst_ptr(gen, inst);
}
JIT_OP_COPY_STRUCT: manual
[] -> {
/* TODO */
TODO();
}
JIT_OP_COPY_STORE_BYTE: manual
[] -> {
arm_inst_buf inst;
int reg;
_jit_regs_force_out(gen, insn->dest, 1);
_jit_gen_fix_value(insn->dest);
reg = _jit_regs_load_value
(gen, insn->value1, 0,
(insn->flags & (JIT_INSN_VALUE1_NEXT_USE |
JIT_INSN_VALUE1_LIVE)));
jit_gen_load_inst_ptr(gen, inst);
arm_store_membase_byte(inst, _jit_reg_info[reg].cpu_reg,
ARM_FP, insn->dest->frame_offset);
jit_gen_save_inst_ptr(gen, inst);
}
JIT_OP_COPY_STORE_SHORT: manual
[] -> {
arm_inst_buf inst;
int reg;
_jit_regs_force_out(gen, insn->dest, 1);
_jit_gen_fix_value(insn->dest);
reg = _jit_regs_load_value
(gen, insn->value1, 1,
(insn->flags & (JIT_INSN_VALUE1_NEXT_USE |
JIT_INSN_VALUE1_LIVE)));
jit_gen_load_inst_ptr(gen, inst);
arm_store_membase_short(inst, _jit_reg_info[reg].cpu_reg,
ARM_FP, insn->dest->frame_offset);
jit_gen_save_inst_ptr(gen, inst);
_jit_regs_free_reg(gen, reg, 1);
}
JIT_OP_ADDRESS_OF: manual
[] -> {
arm_inst_buf inst;
int reg, offset;
_jit_regs_force_out(gen, insn->value1, 0);
_jit_gen_fix_value(insn->value1);
jit_gen_load_inst_ptr(gen, inst);
reg = _jit_regs_dest_value(gen, insn->dest);
reg = _jit_reg_info[reg].cpu_reg;
offset = insn->value1->frame_offset;
if(offset > 0)
{
arm_alu_reg_imm(inst, ARM_ADD, reg, ARM_FP, offset);
}
else if(offset < 0)
{
arm_alu_reg_imm(inst, ARM_SUB, reg, ARM_FP, -offset);
}
else
{
arm_mov_reg_reg(inst, reg, ARM_FP);
}
jit_gen_save_inst_ptr(gen, inst);
}
/*
* Stack pushes and pops.
*/
JIT_OP_RETURN_REG: manual
[] -> { /* Nothing to do here */ }
JIT_OP_PUSH_INT: unary_note
[reg] -> {
arm_push_reg(inst, $1);
}
JIT_OP_PUSH_LONG: unary_note
[lreg] -> {
arm_push_reg(inst, %1);
arm_push_reg(inst, $1);
}
JIT_OP_PUSH_FLOAT32 (JIT_ARM_HAS_FLOAT_REGS): unary_note
[freg] -> {
arm_push_reg_float32(inst, $1);
}
JIT_OP_PUSH_FLOAT32 (!JIT_ARM_HAS_FLOAT_REGS): manual
[] -> {
arm_inst_buf inst;
_jit_regs_force_out(gen, insn->value1, 0);
_jit_gen_fix_value(insn->value1);
jit_gen_load_inst_ptr(gen, inst);
if(insn->value1->is_constant)
{
mov_reg_imm
(gen, &inst, ARM_WORK, ((int *)(insn->value1->address))[0]);
}
else
{
arm_load_membase(inst, ARM_WORK, ARM_FP,
insn->value1->frame_offset);
}
arm_push_reg(inst, ARM_WORK);
jit_gen_save_inst_ptr(gen, inst);
}
JIT_OP_PUSH_FLOAT64, JIT_OP_PUSH_NFLOAT (JIT_ARM_HAS_FLOAT_REGS): unary_note
[freg] -> {
arm_push_reg_float64(inst, $1);
}
JIT_OP_PUSH_FLOAT64, JIT_OP_PUSH_NFLOAT (!JIT_ARM_HAS_FLOAT_REGS): manual
[] -> {
arm_inst_buf inst;
_jit_regs_force_out(gen, insn->value1, 0);
_jit_gen_fix_value(insn->value1);
jit_gen_load_inst_ptr(gen, inst);
if(insn->value1->is_constant)
{
mov_reg_imm
(gen, &inst, ARM_WORK, ((int *)(insn->value1->address))[1]);
arm_push_reg(inst, ARM_WORK);
mov_reg_imm
(gen, &inst, ARM_WORK, ((int *)(insn->value1->address))[0]);
arm_push_reg(inst, ARM_WORK);
}
else
{
arm_load_membase(inst, ARM_WORK, ARM_FP,
insn->value1->frame_offset + 4);
arm_push_reg(inst, ARM_WORK);
arm_load_membase(inst, ARM_WORK, ARM_FP,
insn->value1->frame_offset);
arm_push_reg(inst, ARM_WORK);
}
jit_gen_save_inst_ptr(gen, inst);
}
JIT_OP_PUSH_STRUCT: unary_note
[reg] -> {
/* TODO */
TODO();
}
JIT_OP_POP_STACK:
[] -> {
arm_alu_reg_imm(inst, ARM_ADD, ARM_SP, ARM_SP, insn->value1->address);
}
JIT_OP_FLUSH_SMALL_STRUCT:
[] -> {
jit_nuint size;
jit_nint offset;
_jit_gen_fix_value(insn->value1);
size = jit_type_get_size(jit_value_get_type(insn->value1));
offset = insn->value1->frame_offset;
switch(size)
{
case 1:
{
arm_store_membase_byte(inst, ARM_R0, ARM_FP, offset);
}
break;
case 2:
{
arm_store_membase_short(inst, ARM_R0, ARM_FP, offset);
}
break;
case 3:
{
arm_mov_reg_reg(inst, ARM_R1, ARM_R0);
arm_store_membase_short(inst, ARM_R0, ARM_FP, offset);
arm_shift_reg_imm8(inst, ARM_SHR, ARM_R0, ARM_R1, 16);
arm_store_membase_byte(inst, ARM_R0, ARM_FP, offset + 2);
}
break;
case 4:
{
arm_store_membase(inst, ARM_R0, ARM_FP, offset);
}
break;
case 5:
{
arm_store_membase(inst, ARM_R0, ARM_FP, offset);
arm_store_membase_byte(inst, ARM_R1, ARM_FP, offset + 4);
}
break;
case 6:
{
arm_store_membase(inst, ARM_R0, ARM_FP, offset);
arm_store_membase_short(inst, ARM_R1, ARM_FP, offset + 4);
}
break;
case 7:
{
arm_store_membase(inst, ARM_R0, ARM_FP, offset);
arm_mov_reg_reg(inst, ARM_R2, ARM_R1);
arm_store_membase_short(inst, ARM_R1, ARM_FP, offset + 4);
arm_shift_reg_imm8(inst, ARM_SHR, ARM_R1, ARM_R2, 16);
arm_store_membase_byte(inst, ARM_R1, ARM_FP, offset + 6);
}
break;
case 8:
{
arm_store_membase(inst, ARM_R0, ARM_FP, offset);
arm_store_membase(inst, ARM_R1, ARM_FP, offset + 4);
}
break;
}
}
JIT_OP_SET_PARAM_INT: unary_note
[reg] -> {
arm_store_membase(inst, $1, ARM_SP, insn->value2->address);
}
JIT_OP_SET_PARAM_LONG: unary_note
[lreg] -> {
arm_store_membase(inst, $1, ARM_SP, insn->value2->address);
arm_store_membase(inst, %1, ARM_SP, insn->value2->address + 4);
}
JIT_OP_SET_PARAM_FLOAT32 (JIT_ARM_HAS_FLOAT_REGS): unary_note
[freg] -> {
arm_store_membase_float32(inst, $1, ARM_SP, insn->value2->address);
}
JIT_OP_SET_PARAM_FLOAT32 (!JIT_ARM_HAS_FLOAT_REGS): manual
[] -> {
arm_inst_buf inst;
_jit_regs_force_out(gen, insn->value1, 0);
_jit_gen_fix_value(insn->value1);
jit_gen_load_inst_ptr(gen, inst);
if(insn->value1->is_constant)
{
mov_reg_imm
(gen, &inst, ARM_WORK, ((int *)(insn->value1->address))[0]);
arm_store_membase
(inst, ARM_WORK, ARM_SP, insn->value2->address);
}
else
{
arm_load_membase(inst, ARM_WORK, ARM_FP,
insn->value1->frame_offset);
arm_store_membase
(inst, ARM_WORK, ARM_SP, insn->value2->address);
}
jit_gen_save_inst_ptr(gen, inst);
}
JIT_OP_SET_PARAM_FLOAT64, JIT_OP_SET_PARAM_NFLOAT
(JIT_ARM_HAS_FLOAT_REGS): unary_note
[freg] -> {
arm_store_membase_float64(inst, $1, ARM_SP, insn->value2->address);
}
JIT_OP_SET_PARAM_FLOAT64, JIT_OP_SET_PARAM_NFLOAT
(!JIT_ARM_HAS_FLOAT_REGS): manual
[] -> {
arm_inst_buf inst;
_jit_regs_force_out(gen, insn->value1, 0);
_jit_gen_fix_value(insn->value1);
jit_gen_load_inst_ptr(gen, inst);
if(insn->value1->is_constant)
{
mov_reg_imm
(gen, &inst, ARM_WORK, ((int *)(insn->value1->address))[0]);
arm_store_membase
(inst, ARM_WORK, ARM_SP, insn->value2->address);
mov_reg_imm
(gen, &inst, ARM_WORK, ((int *)(insn->value1->address))[1]);
arm_store_membase
(inst, ARM_WORK, ARM_SP, insn->value2->address + 4);
}
else
{
arm_load_membase(inst, ARM_WORK, ARM_FP,
insn->value1->frame_offset);
arm_store_membase
(inst, ARM_WORK, ARM_SP, insn->value2->address);
arm_load_membase(inst, ARM_WORK, ARM_FP,
insn->value1->frame_offset + 4);
arm_store_membase
(inst, ARM_WORK, ARM_SP, insn->value2->address + 4);
}
jit_gen_save_inst_ptr(gen, inst);
}
JIT_OP_SET_PARAM_STRUCT: unary_note
[reg] -> {
/* TODO */
TODO();
}
/*
* Pointer-relative loads and stores.
*/
JIT_OP_LOAD_RELATIVE_SBYTE: unary
[reg] -> {
arm_load_membase_sbyte(inst, $1, $1, insn->value2->address);
}
JIT_OP_LOAD_RELATIVE_UBYTE: unary
[reg] -> {
arm_load_membase_byte(inst, $1, $1, insn->value2->address);
}
JIT_OP_LOAD_RELATIVE_SHORT: unary
[reg] -> {
arm_load_membase_short(inst, $1, $1, insn->value2->address);
}
JIT_OP_LOAD_RELATIVE_USHORT: unary
[reg] -> {
arm_load_membase_ushort(inst, $1, $1, insn->value2->address);
}
JIT_OP_LOAD_RELATIVE_INT: unary
[reg] -> {
arm_load_membase(inst, $1, $1, insn->value2->address);
}
JIT_OP_LOAD_RELATIVE_LONG: manual
[] -> {
arm_inst_buf inst;
int reg = _jit_regs_load_value
(gen, insn->value1, 0,
(insn->flags & (JIT_INSN_VALUE1_NEXT_USE |
JIT_INSN_VALUE1_LIVE)));
int reg2, reg3;
int frame_offset;
_jit_gen_fix_value(insn->dest);
_jit_regs_get_reg_pair(gen, reg, -1, -1, &reg2, &reg3);
reg = _jit_reg_info[reg].cpu_reg;
reg2 = _jit_reg_info[reg2].cpu_reg;
reg3 = _jit_reg_info[reg3].cpu_reg;
frame_offset = insn->dest->frame_offset;
jit_gen_load_inst_ptr(gen, inst);
arm_load_membase(inst, reg2, reg, insn->value2->address);
arm_load_membase(inst, reg3, reg, insn->value2->address + 4);
arm_store_membase(inst, reg2, ARM_FP, frame_offset);
arm_store_membase(inst, reg3, ARM_FP, frame_offset + 4);
insn->dest->in_frame = 1;
jit_gen_save_inst_ptr(gen, inst);
}
JIT_OP_LOAD_RELATIVE_FLOAT32: manual
[] -> {
/* TODO */
TODO();
}
JIT_OP_LOAD_RELATIVE_FLOAT64, JIT_OP_LOAD_RELATIVE_NFLOAT: manual
[] -> {
/* TODO */
TODO();
}
JIT_OP_LOAD_RELATIVE_STRUCT: manual
[] -> {
/* TODO */
TODO();
}
JIT_OP_STORE_RELATIVE_BYTE: manual
[] -> {
arm_inst_buf inst;
int reg = _jit_regs_load_value
(gen, insn->dest, 0,
(insn->flags & (JIT_INSN_DEST_NEXT_USE |
JIT_INSN_DEST_LIVE)));
int reg2 = _jit_regs_load_value
(gen, insn->value1, 0,
(insn->flags & (JIT_INSN_VALUE1_NEXT_USE |
JIT_INSN_VALUE1_LIVE)));
jit_gen_load_inst_ptr(gen, inst);
reg = _jit_reg_info[reg].cpu_reg;
reg2 = _jit_reg_info[reg2].cpu_reg;
arm_store_membase_byte(inst, reg2, reg, insn->value2->address);
jit_gen_save_inst_ptr(gen, inst);
}
JIT_OP_STORE_RELATIVE_SHORT: manual
[] -> {
arm_inst_buf inst;
int reg = _jit_regs_load_value
(gen, insn->dest, 0,
(insn->flags & (JIT_INSN_DEST_NEXT_USE |
JIT_INSN_DEST_LIVE)));
int reg2 = _jit_regs_load_value
(gen, insn->value1, 1,
(insn->flags & (JIT_INSN_VALUE1_NEXT_USE |
JIT_INSN_VALUE1_LIVE)));
jit_gen_load_inst_ptr(gen, inst);
reg = _jit_reg_info[reg].cpu_reg;
reg2 = _jit_reg_info[reg2].cpu_reg;
arm_store_membase_short(inst, reg2, reg, insn->value2->address);
jit_gen_save_inst_ptr(gen, inst);
_jit_regs_free_reg(gen, reg2, 1);
}
JIT_OP_STORE_RELATIVE_INT: manual
[] -> {
arm_inst_buf inst;
int reg = _jit_regs_load_value
(gen, insn->dest, 0,
(insn->flags & (JIT_INSN_DEST_NEXT_USE |
JIT_INSN_DEST_LIVE)));
int reg2 = _jit_regs_load_value
(gen, insn->value1, 0,
(insn->flags & (JIT_INSN_VALUE1_NEXT_USE |
JIT_INSN_VALUE1_LIVE)));
jit_gen_load_inst_ptr(gen, inst);
reg = _jit_reg_info[reg].cpu_reg;
reg2 = _jit_reg_info[reg2].cpu_reg;
arm_store_membase(inst, reg2, reg, insn->value2->address);
jit_gen_save_inst_ptr(gen, inst);
}
JIT_OP_STORE_RELATIVE_LONG: manual
[] -> {
arm_inst_buf inst;
int reg = _jit_regs_load_value
(gen, insn->dest, 0,
(insn->flags & (JIT_INSN_DEST_NEXT_USE |
JIT_INSN_DEST_LIVE)));
int reg2, reg3;
int frame_offset;
_jit_regs_get_reg_pair(gen, reg, -1, -1, &reg2, &reg3);
_jit_gen_fix_value(insn->value1);
jit_gen_load_inst_ptr(gen, inst);
reg = _jit_reg_info[reg].cpu_reg;
reg2 = _jit_reg_info[reg2].cpu_reg;
reg3 = _jit_reg_info[reg3].cpu_reg;
frame_offset = insn->value1->frame_offset;
arm_load_membase(inst, reg2, ARM_FP, frame_offset);
arm_load_membase(inst, reg3, ARM_FP, frame_offset + 4);
arm_store_membase(inst, reg2, reg, insn->value2->address);
arm_store_membase(inst, reg3, reg, insn->value2->address + 4);
jit_gen_save_inst_ptr(gen, inst);
}
JIT_OP_STORE_RELATIVE_FLOAT32: manual
[] -> {
/* TODO */
TODO();
}
JIT_OP_STORE_RELATIVE_FLOAT64, JIT_OP_STORE_RELATIVE_NFLOAT: manual
[] -> {
/* TODO */
TODO();
}
JIT_OP_STORE_RELATIVE_STRUCT: manual
[] -> {
/* TODO */
TODO();
}
JIT_OP_ADD_RELATIVE: unary
[reg] -> {
if(insn->value2->address != 0)
{
arm_alu_reg_imm(inst, ARM_ADD, $1, $1, insn->value2->address);
}
}