Esempio n. 1
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;
}
Esempio n. 2
0
void Compiler::gen_switch(const JInst & jinst)
{
    assert(jinst.opcode == OPCODE_LOOKUPSWITCH 
           || jinst.opcode == OPCODE_TABLESWITCH);
    Opnd val = vstack(0, true).as_opnd();
    vpop();
    rlock(val);
    gen_bb_leave(NOTHING);

    if (jinst.opcode == OPCODE_LOOKUPSWITCH) {
        unsigned n = jinst.get_num_targets();
        for (unsigned i = 0; i < n; i++) {
            Opnd key(jinst.key(i));
            unsigned pc = jinst.get_target(i);
            alu(alu_cmp, val, key);
            br(eq, pc, m_bbinfo->start);
        }
        runlock(val);
        br(cond_none, jinst.get_def_target(), m_bbinfo->start);
        return;
    }
    //
    // TABLESWITCH
    //
    alu(alu_cmp, val, jinst.high());
    br(gt, jinst.get_def_target(), m_bbinfo->start);
    
    alu(alu_cmp, val, jinst.low());
    br(lt, jinst.get_def_target(), m_bbinfo->start);
    
    AR gr_tabl = valloc(jobj);
    movp(gr_tabl, DATA_SWITCH_TABLE | m_curr_inst->pc, m_bbinfo->start);
#ifdef _EM64T_
    // On EM64T, we operate with I_32 value in a register, but the 
    // register will be used as 64 bit in address form - have to extend
    sx(Opnd(i64, val.reg()), Opnd(i32, val.reg()));
#endif
    // Here, we need to extract 'index-=low()' - can pack this into 
    // complex address form:
    //      [table + index*sizeof(void*) - low()*sizeof(void*)],
    // but only if low()*sizeof(void*) does fit into displacement ...
    int tmp = -jinst.low();
    const int LO_BOUND = INT_MIN/(int)sizeof(void*);
    const int UP_BOUND = INT_MAX/(int)sizeof(void*);
    if (LO_BOUND<=tmp && tmp<=UP_BOUND) {
        ld(jobj, gr_tabl, gr_tabl, -jinst.low()*sizeof(void*), 
        val.reg(), sizeof(void*));
    }
    else {
        // ... otherwise subtract explicitly, but only if the register
        // is not used anywhere else
        if (rrefs(val.reg()) !=0) {
            Opnd vtmp(i32, valloc(i32));
            mov(vtmp, val); // make a copy of val
            runlock(val);
            val = vtmp;
            rlock(val);
        }
        alu(alu_sub, val, jinst.low());
        ld(jobj, gr_tabl, gr_tabl, 0, val.reg(), sizeof(void*));
    }
    runlock(val);
    br(gr_tabl);
}