bool IpfVerifier::cmp_cmp4()

in vm/jitrino/src/codegenerator/ipf/IpfVerifier.cpp [715:876]


bool IpfVerifier::cmp_cmp4(string * res, Inst * inst, InstCode icode, OpndVector & opnds, CompVector & cmpls) {
    if (!IS_O(4) || !IS_C(0)) return false;
    if (!IS_PR(1) || !IS_PR(2) || !(IS_GR(3) || IS_IMM(3)) || !IS_GR(4)) return false;
    if (IS_GR(3) && IS_GR(4)) {
//        if (GR(3)->getDataKind() != GR(4)->getDataKind()) {
//            res->append(IrPrinter::toString(O(3)) 
//                + " and " 
//                + IrPrinter::toString(O(4))
//                + " have different DataKind: "
//                + getDataKindStr(GR(3)->getDataKind())
//                + ", "
//                + getDataKindStr(GR(4)->getDataKind()));
//            return false;
//        }
    }
    
    int64 p1=V(1), p2=V(2);
    int64 r2=V(3), r3=V(4);
    OpndKind okind3=K(3);
    Completer crel = C(0);
    Completer ctype = ( IS_C(1) ? C(1) : CMPLT_INVALID );
    uint64 opcode=0, ta=0, c=0, x2;
    int64 tmp;

    // parse pseudo-op    
    if ( !IS_C(1) || ctype==CMPLT_CMP_CTYPE_UNC ) {
        if ( IS_IMM8(3) ) {
            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: 
            return false;
        }
    }

    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: 
        return false;
    }
    
    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 true;
    } else if ( IS_IMM8(3) ) {
        x2 = icode==INST_CMP ? 2 : 3;
        return true;
    } else {
        if (r2!=0) return false;
        x2 = icode==INST_CMP ? 0 : 1;
        return true;
    }
    return false;
}