/* * 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); }
/* * Flush the contents of the constant pool. */ static void flush_constants(jit_gencode_t gen, int after_epilog) { arm_inst_buf inst; arm_inst_word *patch; arm_inst_word *current; arm_inst_word *fixup; int index, value, offset; /* Bail out if there are no constants to flush */ if(!(gen->num_constants)) { return; } /* Initialize the cache output pointer */ jit_gen_load_inst_ptr(gen, inst); /* Jump over the constant pool if it is being output inline */ if(!after_epilog) { patch = arm_inst_get_posn(inst); arm_jump_imm(inst, 0); } else { patch = 0; } /* Align the constant pool, if requested */ if(gen->align_constants && (((int)arm_inst_get_posn(inst)) & 7) != 0) { arm_inst_add(inst, 0); } /* Output the constant values and apply the necessary fixups */ for(index = 0; index < gen->num_constants; ++index) { current = arm_inst_get_posn(inst); arm_inst_add(inst, gen->constants[index]); fixup = gen->fixup_constants[index]; while(fixup != 0) { if((*fixup & 0x0F000000) == 0x05000000) { /* Word constant fixup */ value = *fixup & 0x0FFF; offset = ((arm_inst_get_posn(inst) - 1 - fixup) * 4) - 8; *fixup = ((*fixup & ~0x0FFF) | offset); } else { /* Floating-point constant fixup */ value = (*fixup & 0x00FF) * 4; offset = ((arm_inst_get_posn(inst) - 1 - fixup) * 4) - 8; *fixup = ((*fixup & ~0x00FF) | (offset / 4)); } if(value) { fixup -= value; } else { fixup = 0; } } } /* Backpatch the jump if necessary */ if(!after_epilog) { arm_patch(inst, patch, arm_inst_get_posn(inst)); } /* Flush the pool state and restart */ gen->num_constants = 0; gen->align_constants = 0; gen->first_constant_use = 0; jit_gen_save_inst_ptr(gen, inst); }