uint64 Encoder::cmp_cmp4()

in vm/jitrino/src/codegenerator/ipf/IpfEncoder.cpp [1390:1542]


uint64 Encoder::cmp_cmp4(InstCode icode, Inst * inst, CompVector & cmpls, OpndVector & opnds, uint64 qp) {
    assert(opnds.size()>=5);
    
    int64 p1=opnds[1]->getValue(), p2=opnds[2]->getValue();
    int64 r2=opnds[3]->getValue(), r3=opnds[4]->getValue();
    OpndKind okind3=opnds[3]->getOpndKind();
    Completer crel = cmpls[0];
    Completer ctype = ( cmpls.size()>1 ? cmpls[1] : CMPLT_INVALID );
    uint64 opcode=0, ta=0, c=0, x2;
    int64 tmp, & imm8 = r2;

    // parse pseudo-op    
    if ( cmpls.size() == 1 || ctype==CMPLT_CMP_CTYPE_UNC ) {
        if (opnds[3]->isImm(8)) {
            switch (crel) {
            case CMPLT_CMP_CREL_NE:
                crel=CMPLT_CMP_CREL_EQ; 
                tmp = p1; p1 = p2; p2 = tmp;   
                break;
            case CMPLT_CMP_CREL_LE:
                crel=CMPLT_CMP_CREL_LT;
                r2--;   
                break;
            case CMPLT_CMP_CREL_GT:
                crel=CMPLT_CMP_CREL_LT;
                r2--;   
                tmp = p1; p1 = p2; p2 = tmp;   
                break;
            case CMPLT_CMP_CREL_GE:
                crel=CMPLT_CMP_CREL_LT;
                tmp = p1; p1 = p2; p2 = tmp;   
                break;
            case CMPLT_CMP_CREL_LEU: 
                crel=CMPLT_CMP_CREL_LTU;
                r2--;   
                break;
            case CMPLT_CMP_CREL_GTU: 
                crel=CMPLT_CMP_CREL_LTU;
                r2--;   
                tmp = p1; p1 = p2; p2 = tmp;   
                break;
            case CMPLT_CMP_CREL_GEU: 
                crel=CMPLT_CMP_CREL_LTU;
                tmp = p1; p1 = p2; p2 = tmp;   
                break;
            default: 
                break;
            }
        } else {
            switch (crel) {
            case CMPLT_CMP_CREL_NE:
                crel=CMPLT_CMP_CREL_EQ; 
                tmp = p1; p1 = p2; p2 = tmp;   
                break;
            case CMPLT_CMP_CREL_LE:
                crel=CMPLT_CMP_CREL_LT;
                tmp = r3; r3 = r2; r2 = tmp;   
                tmp = p1; p1 = p2; p2 = tmp;   
                break;
            case CMPLT_CMP_CREL_GT:
                crel=CMPLT_CMP_CREL_LT;
                tmp = r3; r3 = r2; r2 = tmp;   
                break;
            case CMPLT_CMP_CREL_GE:
                crel=CMPLT_CMP_CREL_LT;
                tmp = p1; p1 = p2; p2 = tmp;   
                break;
            case CMPLT_CMP_CREL_LEU: 
                crel=CMPLT_CMP_CREL_LTU;
                tmp = r3; r3 = r2; r2 = tmp;   
                tmp = p1; p1 = p2; p2 = tmp;   
                break;
            case CMPLT_CMP_CREL_GTU: 
                crel=CMPLT_CMP_CREL_LTU;
                tmp = r3; r3 = r2; r2 = tmp;   
                break;
            case CMPLT_CMP_CREL_GEU: 
                crel=CMPLT_CMP_CREL_LTU;
                tmp = p1; p1 = p2; p2 = tmp;   
                break;
            default: 
                break;
            }
        }
    } else if ( crel!=CMPLT_CMP_CREL_EQ && crel!=CMPLT_CMP_CREL_NE ) {
        if ( crel==CMPLT_CMP_CREL_LT && r2>0 ) {
            crel=CMPLT_CMP_CREL_GT;
            tmp = r3; r3 = r2; r2 = tmp;   
        } else if ( crel==CMPLT_CMP_CREL_LE && r2>0 ) {
            crel=CMPLT_CMP_CREL_GE;
            tmp = r3; r3 = r2; r2 = tmp;   
        } else if ( crel==CMPLT_CMP_CREL_GT && r2>0 ) {
            crel=CMPLT_CMP_CREL_LT;
            tmp = r3; r3 = r2; r2 = tmp;   
        } else if ( crel==CMPLT_CMP_CREL_GE && r2>0 ) {
            crel=CMPLT_CMP_CREL_LE;
            tmp = r3; r3 = r2; r2 = tmp;   
        }
    }

    switch (ctype) {
    case CMPLT_CMP_CTYPE_AND:      opcode=0xC; break;
    case CMPLT_CMP_CTYPE_OR:       opcode=0xD; break;
    case CMPLT_CMP_CTYPE_OR_ANDCM: opcode=0xE; break;
    default: 
        switch (crel) {
        case CMPLT_CMP_CREL_LT:  opcode=0xC; break;
        case CMPLT_CMP_CREL_LTU: opcode=0xD; break;
        case CMPLT_CMP_CREL_EQ:  opcode=0xE; break;
        default: 
            IPF_ERR << __FILE__ << ": " << __LINE__ << ": BAD ctype/crel\n";
            assert(0);
            break;
        }
    }

    switch (crel) {
    case CMPLT_CMP_CREL_NE:  ta=1; c=1; break;
    case CMPLT_CMP_CREL_GE:  ta=1; c=0; break;
    case CMPLT_CMP_CREL_LE:  ta=0; c=1; break;
    case CMPLT_CMP_CREL_GT:  ta=0; c=0; break;
    case CMPLT_CMP_CREL_LTU: ta=0; c=(ctype==CMPLT_CMP_CTYPE_UNC ? 1 : 0); break;
    case CMPLT_CMP_CREL_EQ:  
        if ( cmpls.size()==1 ) { ta=0; c=0; }
        else if ( ctype==CMPLT_CMP_CTYPE_UNC ) { ta=0; c=1; }
        else { ta=1; c=0; }
        break;
    case CMPLT_CMP_CREL_LT:  
        if ( cmpls.size()==1 ) { ta=0; c=0; }
        else if ( ctype==CMPLT_CMP_CTYPE_UNC ) { ta=0; c=1; }
        else { ta=1; c=1; }
        break;
    default: 
        IPF_ERR << __FILE__ << ": " << __LINE__ << ": BAD ctype/crel\n";
        assert(0);
        break;
    }
    
    if ( (ctype==CMPLT_CMP_CTYPE_NORMAL || ctype==CMPLT_CMP_CTYPE_UNC 
            || crel==CMPLT_CMP_CREL_NE || crel==CMPLT_CMP_CREL_EQ || cmpls.size()==1) 
            && okind3==OPND_G_REG ) {
        x2 = icode==INST_CMP ? 0 : 1;
        return A6(opcode, x2, ta, c, p1, p2, r2, r3, qp);
    } else if (opnds[3]->isImm(8)) {
        x2 = icode==INST_CMP ? 2 : 3;
        return A8(opcode, x2, ta, c, p1, p2, imm8, r3, qp);
    } else {
        assert(r2==0);
        x2 = icode==INST_CMP ? 0 : 1;
        return A7(opcode, x2, ta, c, p1, p2, r3, qp);
    }
    
}