/* * Check a 2D array access operation for exception conditions. */ static void Check2DArrayAccess(MDUnroll *unroll, int reg, int reg2, int reg3, unsigned char *pc, unsigned char *label) { #ifndef IL_USE_INTERRUPT_BASED_NULL_POINTER_CHECKS md_inst_ptr patch1; #endif md_inst_ptr patch2; md_inst_ptr patch3; #ifndef IL_USE_INTERRUPT_BASED_NULL_POINTER_CHECKS /* Check the array reference against NULL */ arm_test_reg_imm8(unroll->out, ARM_CMP, reg, 0); patch1 = unroll->out; arm_branch_imm(unroll->out, ARM_CC_EQ, 0); #endif /* Check the array bounds. We assume that we can use the link register as a work register because "lr" would have been saved on entry to "_ILCVMInterpreter" */ arm_load_membase(unroll->out, ARM_WORK, reg, 12); arm_alu_reg_reg(unroll->out, ARM_SUB, reg2, reg2, ARM_WORK); arm_load_membase(unroll->out, ARM_LINK, reg, 16); arm_test_reg_reg(unroll->out, ARM_CMP, reg2, ARM_LINK); patch2 = unroll->out; arm_branch_imm(unroll->out, ARM_CC_LT_UN, 0); arm_alu_reg_reg(unroll->out, ARM_ADD, reg2, reg2, ARM_WORK); patch3 = unroll->out; arm_jump_imm(unroll->out, 0); arm_patch(patch2, unroll->out); arm_load_membase(unroll->out, ARM_WORK, reg, 24); arm_alu_reg_reg(unroll->out, ARM_SUB, reg3, reg3, ARM_WORK); arm_load_membase(unroll->out, ARM_LINK, reg, 28); arm_test_reg_reg(unroll->out, ARM_CMP, reg3, ARM_LINK); patch2 = unroll->out; arm_branch_imm(unroll->out, ARM_CC_LT_UN, 0); arm_alu_reg_reg(unroll->out, ARM_ADD, reg3, reg3, ARM_WORK); arm_load_membase(unroll->out, ARM_WORK, reg, 12); arm_alu_reg_reg(unroll->out, ARM_ADD, reg2, reg2, ARM_WORK); /* Re-execute the current instruction in the interpreter */ #ifndef IL_USE_INTERRUPT_BASED_NULL_POINTER_CHECKS arm_patch(patch1, unroll->out); #endif arm_patch(patch3, unroll->out); ReExecute(unroll, pc, label); /* Compute the address of the array element */ arm_patch(patch2, unroll->out); arm_load_membase(unroll->out, ARM_WORK, reg, 20); arm_mul_reg_reg(unroll->out, reg2, reg2, ARM_WORK); arm_load_membase(unroll->out, ARM_WORK, reg, 32); arm_mul_reg_reg(unroll->out, reg3, reg3, ARM_WORK); arm_alu_reg_reg(unroll->out, ARM_ADD, reg2, reg2, reg3); arm_load_membase(unroll->out, ARM_WORK, reg, 4); arm_mul_reg_reg(unroll->out, reg2, reg2, ARM_WORK); arm_load_membase(unroll->out, reg, reg, 8); arm_alu_reg_reg(unroll->out, ARM_ADD, reg, reg, reg2); }
void *_jit_gen_redirector(jit_gencode_t gen, jit_function_t func) { void *ptr, *entry; arm_inst_buf inst; jit_gen_load_inst_ptr(gen, inst); ptr = (void *)&(func->entry_point); entry = gen->posn.ptr; arm_load_membase(inst, ARM_WORK, ARM_PC, 0); arm_load_membase(inst, ARM_PC, ARM_WORK, 0); arm_inst_add(inst, (unsigned int)ptr); jit_gen_save_inst_ptr(gen, inst); return entry; }
/* * Load an immediate value into a word register. If the value is * complicated, then add an entry to the constant pool. */ static void mov_reg_imm (jit_gencode_t gen, arm_inst_buf *inst, int reg, int value) { arm_inst_word *fixup; /* Bail out if the value is not complex enough to need a pool entry */ if(!arm_is_complex_imm(value)) { arm_mov_reg_imm(*inst, reg, value); return; } /* Output a placeholder to load the value later */ fixup = arm_inst_get_posn(*inst); arm_load_membase(*inst, reg, ARM_PC, 0); /* Add the constant to the pool, which may cause a flush */ jit_gen_save_inst_ptr(gen, *inst); add_constant(gen, value, fixup); jit_gen_load_inst_ptr(gen, *inst); }