Esempio n. 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;
}
Esempio n. 2
0
bool CodeGen::gen_a_generic(JavaByteCodes op, jtype jt)
{
    if (op == OPCODE_INEG) {
        return false; // later
    }
    if (jt == i32) {
        bool v2_imm = vis_imm(0);
        if (v2_imm &&
            (op == OPCODE_ISHL || op == OPCODE_ISHL || op == OPCODE_IUSHR)) {
            // accept it
        }
        /*else if (v2_imm && (op == OPCODE_IMUL || op == OPCODE_IDIV)) {
            // accept it
        }
        else if (op == OPCODE_IMUL) {
            // accept it
        }*/
        else if (op == OPCODE_IADD || op == OPCODE_ISUB) {
            // accept it
        }
        else if (op == OPCODE_IOR || op == OPCODE_IAND || op == OPCODE_IXOR) {
            // accept it
        }
        else if (vis_imm(0) && m_jframe->size()>1 && vis_imm(1)) {
            // accept it
        }
        else {
            return false;
        }
    }
    else if (is_f(jt)) {
        if (op != OPCODE_IADD && op != OPCODE_ISUB && 
            op != OPCODE_IMUL && op != OPCODE_IDIV) {
            return false;    
        }
    }
    else {
        return false;
    }
    
    bool is_dbl = jt == dbl64;
    unsigned v1_depth = is_dbl?2:1;
    
    if (vis_imm(v1_depth) && vis_imm(0)) {
        const Val& v1 = m_jframe->dip(v1_depth);
        const Val& v2 = m_jframe->dip(0);
        Val res;
        if (jt==dbl64) {
            double d = rt_h_dbl_a(v1.dval(), v2.dval(), op);
            res = Val(d);
        }
        else if (jt==flt32) {
            float f = rt_h_flt_a(v1.fval(), v2.fval(), op);
            res = Val(f);
        }
        else {
            assert(jt==i32);
            int i = rt_h_i32_a(v1.ival(), v2.ival(), op);
            res = Val(i);
        }
        vpop();
        vpop();
        vpush(res);
        return true;
    } // if v1.is_imm() && v2.is_imm()
    

    const Val& v1 = vstack(v1_depth, true);
    Opnd res = v1.as_opnd();
    if (rrefs(v1.reg()) > 1) {
        rlock(v1);
        AR ar = valloc(jt);
        runlock(v1);
        Opnd reg(jt, ar);
        mov(reg, v1.as_opnd());
        res = reg;
    }
    rlock(res);
    rlock(v1);
    const Val& v2 = m_jframe->dip(0);
/*    if (false )v2.
        
#ifdef _IA32_
        // on IA32 can use address in a displacement
        alu(to_alu(op), v1, ar_x, (int)v2.addr());
#else
        AR addr = valloc(jobj); rlock(addr);
        movp(addr, v2.addr());
        alu_mem(jt, to_alu(op), r1, addr);
        runlock(addr);
#endif
    }
    else */
    if(v2.is_mem()) {
        // Everyone can do 'reg, mem' operation
        alu(to_alu(op), res, v2.as_opnd());
    }
    else if(v2.is_imm() && jt==i32) {
        // 'reg, imm' is only for i32 operations
        alu(to_alu(op), res, v2.ival());
    }
    else {
        Opnd v2 = vstack(0, true).as_opnd();
        alu(to_alu(op), res, v2);
    }
    vpop();
    vpop();
    runlock(v1);
    runlock(res);
    vpush(res);

    return true;
}