Beispiel #1
0
void Compiler::handle_ik_cf(const JInst& jinst) {
    switch(jinst.opcode) {
    case OPCODE_IFNULL:
    case OPCODE_IFNONNULL:
    case OPCODE_IFEQ:
    case OPCODE_IFNE:
    case OPCODE_IFLT:
    case OPCODE_IFGE:
    case OPCODE_IFGT:
    case OPCODE_IFLE:
        gen_if(jinst.opcode, jinst.get_target(0));
        break;
    case OPCODE_IF_ACMPEQ:
    case OPCODE_IF_ACMPNE:
    case OPCODE_IF_ICMPEQ:
    case OPCODE_IF_ICMPNE:
    case OPCODE_IF_ICMPLT:
    case OPCODE_IF_ICMPGE:
    case OPCODE_IF_ICMPGT:
    case OPCODE_IF_ICMPLE:
        gen_if_icmp(jinst.opcode, jinst.get_target(0));
        break;
    case OPCODE_GOTO:
    case OPCODE_GOTO_W:
        gen_goto(jinst.get_target(0));
        break;
    case OPCODE_JSR:
    case OPCODE_JSR_W:
        gen_jsr(jinst.get_target(0));
        break;
    case OPCODE_RET:
        gen_ret(jinst.op0);
        break;
    case OPCODE_TABLESWITCH:
    case OPCODE_LOOKUPSWITCH:
        gen_switch(jinst);
        break;
    default: assert(false); break;
    }
}
Beispiel #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);
}