/** * Provides fine-tuned implementation for IDIV/IREM operations on IA32-compatible platforms, * in replacement of common arithmetic helper (see arith_rt.h). */ bool CodeGen::gen_a_platf(JavaByteCodes op, jtype jt) { if (jt != i32) return false; if (op != OPCODE_IDIV && op != OPCODE_IREM) { return false; } // // The method is supposed to be platform-depended, and may not have // Encoder support - leaving as-is, without implementing general // support in Encoder // vpark(eax.reg()); vpark(edx.reg()); rlock(eax); rlock(edx); Val& v1 = vstack(1, vis_imm(1)); Val& v2 = vstack(0, true); alu(alu_cmp, v2.as_opnd(), Opnd(-1)); unsigned br_normal = br(ne, 0, 0); alu(alu_cmp, v1.as_opnd(), Opnd(INT_MIN)); unsigned br_exit = NOTHING; if (op == OPCODE_IREM) { do_mov(edx, Opnd(0)); // prepare exit value for the corner case br_exit = br(eq, 0, 0); } else { do_mov(eax, v1); br_exit = br(eq, 0, 0); } patch(br_normal, ip()); do_mov(eax, v1); // // The method is supposed to be platform-depended, and may not have // Encoder support - leaving as-is, without implementing general // support in Encoder // //CDQ EncoderBase::Operands args0(RegName_EDX, RegName_EAX); ip(EncoderBase::encode(ip(), Mnemonic_CDQ, args0)); //IDIV EncoderBase::Operands args(RegName_EDX, RegName_EAX, devirt(v2.reg(), i32)); ip(EncoderBase::encode(ip(), Mnemonic_IDIV, args)); patch(br_exit, ip()); vpop(); vpop(); vpush(op == OPCODE_IREM ? edx : eax); runlock(eax); runlock(edx); return true; }
void Compiler::handle_inst(void) { // is it last instruction in basic block ? //const bool last = m_bbinfo->last_pc == jinst.pc; const JInst& jinst = m_insts[m_pc]; unsigned bc_size = m_infoBlock.get_bc_size(); bool lastInBB = jinst.next>=bc_size || (m_insts[jinst.next].flags & OPF_STARTS_BB); if (is_set(DBG_CHECK_STACK)) { gen_dbg_check_stack(true); } // First test if this is a magic. If not, then proceed with regular // code gen. if (!gen_magic()) { const InstrDesc& idesc = instrs[jinst.opcode]; switch (idesc.ik) { case ik_a: handle_ik_a(jinst); break; case ik_cf: handle_ik_cf(jinst); break; case ik_cnv: handle_ik_cnv(jinst); break; case ik_ls: handle_ik_ls(jinst); break; case ik_meth: handle_ik_meth(jinst); break; case ik_obj: handle_ik_obj(jinst); break; case ik_stack: handle_ik_stack(jinst); break; case ik_throw: gen_athrow(); break; default: assert(jinst.opcode == OPCODE_NOP); break; } // ~switch(opcodegroup) } else { // if (!gen_magic()) { // no op. Just check stack (if applicable) and do mem manipulations } if (is_set(DBG_CHECK_STACK)) { gen_dbg_check_stack(false); } if (g_jvmtiMode) { // Do not allow values to cross instruction boundaries // on a temporary registers vpark(); // We must have GC info at every bytecode instruction // to support possible enumeration at a breakpoint gen_gc_stack(-1, false); } const bool has_fall_through = !jinst.is_set(OPF_DEAD_END); if (lastInBB && has_fall_through && jinst.get_num_targets() == 0) { gen_bb_leave(jinst.next); } }