示例#1
0
/**
 * 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;
}
示例#2
0
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);
    }
}