bool IpfVerifier::verifyInst()

in vm/jitrino/src/codegenerator/ipf/IpfVerifier.cpp [158:538]


bool IpfVerifier::verifyInst(string * res, Inst * inst) {
    InstCode   icode  = inst->getInstCode();
    OpndVector & opnds = inst->getOpnds();
    CompVector & cmpls = inst->getComps();

    if ( !IS_PR(0) ) return false;

    switch (icode) {
    // special cases
    case INST_NOP:
        return true;
    case INST_HINT:
        return true;
    case INST_BREAK:
        return true;
    case INST_BREAKPOINT:
        return true;

    case INST_BR13:
    case INST_BRL13: 
    case INST_BR:
    case INST_BRL:
    case INST_BRP:
    case INST_BRP_RET:
        return br(res, inst, icode, opnds, cmpls);
        
    case INST_ADD:
        if (!IS_O(3)) return false;
        if (IS_GR(1) && IS_GR(2) && IS_GR(3)) return true;
        if (IS_GR(1) && IS_IMM14(2) && IS_GR(3)) return true;
        if (IS_GR(1) && IS_IMM22(2) && IS_GR(3)) {
            if (V(2)<=3 && V(2)>=0) return true;
        }
        break;;
    case INST_ADDS:
        if (!IS_O(3)) return false;
        if (IS_GR(1) && IS_IMM14(2) && IS_GR(3)) return true;
        break;;
    case INST_ADDL: // opnds[2]->getOpndKind() == OPND_IMM22
        if (!IS_O(3)) return false;
        if (IS_GR(1) && IS_IMM22(2) && IS_GR(3)) {
            if (opnds[2]->getValue()<=3 && opnds[2]->getValue()>=0) return true;
        }
        break;;
    case INST_ADDP4:
        if (!IS_O(3)) return false;
        if (IS_GR(1) && IS_GR(2) && IS_GR(3)) return true;
        if (IS_GR(1) && IS_IMM14(2) && IS_GR(3)) return true;
        break;
    case INST_ALLOC:
        if (!IS_O(5)) return false;
        if (IS_GR(1) && IS_IMM(2) && IS_IMM(3) && IS_IMM(4) && IS_IMM(5)) {
            if (V(0)!=0) return false;
            if ((V(2) + V(3) + V(4))>96) return false;
            if (V(5)>(V(2) + V(3) + V(4))) return false;
            if ((V(2) + V(3))>(V(2) + V(3) + V(4))) return false;
            if (V(5)%8 != 0) return false;
            return true;
        }
        break;
    case INST_AND: 
    case INST_ANDCM:
    case INST_OR:
    case INST_XOR:
        if (!IS_O(3)) return false;
        if (IS_GR(1) && IS_GR(2) && IS_GR(3)) return true;
        if (IS_GR(1) && IS_IMM8(2) && IS_GR(3)) return true;
        break;
    case INST_SUB:
        if (!IS_O(3)) return false;
        if (IS_GR(1) && IS_GR(2) && IS_GR(3) && IS_O(4)) {
            if (IS_IMM(4) && V(4)==1) return true;
            return false;
        }
        if (IS_GR(1) && IS_GR(2) && IS_GR(3)) return true;
        if (IS_GR(1) && IS_IMM8(2) && IS_GR(3)) return true;
        break;
    case INST_CMP:
    case INST_CMP4:
        return cmp_cmp4(res, inst, icode, opnds, cmpls);
    case INST_FABS:
        if (!IS_O(2)) return false;
        if (IS_FR(1) && IS_FR(2)) return true;
        break;
    case INST_FADD:
        {
            uint64 opcode=8, x=0, sf=0;
            
            if (!IS_O(3) || IS_O(4)) return false;
            if (!(IS_FR(1) && IS_FR(2) && IS_FR(3))) return false;
            for (uint64 i=0 ; IS_C(i) ; i++ ) {
                switch (C(i)) {
                case CMPLT_PC_DYNAMIC: x=0; opcode=8; break;
                case CMPLT_PC_SINGLE:  x=1; opcode=8; break;
                case CMPLT_PC_DOUBLE:  x=0; opcode=9; break;
                case CMPLT_SF0: sf=0; break;
                case CMPLT_SF1: sf=1; break;
                case CMPLT_SF2: sf=2; break;
                case CMPLT_SF3: sf=3; break;
                default: return false;
                }
            }
            return true;
        }
    case INST_FAND:
    case INST_FANDCM:
        if ( !IS_O(3) || IS_O(4)) return false;
        if (IS_FR(1) && IS_FR(2) && IS_FR(3)) return true;
        break;
    case INST_FC:
    case INST_FC_I:
        if (IS_GR(1) && !IS_O(2)) return true;
        break;
    case INST_FCMP:
        return fcmp(res, inst, icode, opnds, cmpls);
    case INST_FCLASS:
        if (!IS_O(4) || IS_O(5)) return false;
        for (unsigned int i=0 ; IS_C(i) ; ++i) {
            if ( !(C(i)==CMPLT_FCMP_FCTYPE_UNC
                    || C(i)==CMPLT_FCMP_FCTYPE_NONE
                    || C(i)==CMPLT_FCMP_FCTYPE_NORMAL
                    || C(i)==CMPLT_FCREL_NM
                    || C(i)==CMPLT_FCREL_M) ) {
                return false;
            }
        }
        if (IS_PR(1) && IS_PR(2) && IS_FR(3) && IS_IMM9(4)) return true;
        
        break;
    case INST_FCVT_FX: 
    case INST_FCVT_FX_TRUNC: 
    case INST_FCVT_FXU: 
    case INST_FCVT_FXU_TRUNC: 
        if ( IS_C(0) ) {
            switch(C(0)) {
            case CMPLT_SF0:
            case CMPLT_SF1:
            case CMPLT_SF2:
            case CMPLT_SF3:
                break;
            default:
                return false;
            }
        }
        if (IS_FR(1) && IS_FR(2)) return true;
        break;
    case INST_FCVT_XF:
        if (IS_FR(1) && IS_FR(2)) return true;
        break;
    case INST_FCVT_XUF:
        if (IS_C(2)) return false;
        for (U_32 i=0 ; IS_C(i) ; i++) {
            switch (C(i)) {
            case CMPLT_PC_SINGLE:  
            case CMPLT_PC_DOUBLE:  
            case CMPLT_PC_DYNAMIC:
            case CMPLT_SF0:
            case CMPLT_SF1:
            case CMPLT_SF2:
            case CMPLT_SF3:
                break;
            default:
                return false;
            }
        }
        if (IS_FR(1) && IS_FR(2)) return true;
        break;
    case INST_FMA:
        for (U_32 i=0 ; IS_C(i) ; i++) {
            switch (C(i)) {
            case CMPLT_PC_SINGLE:  
            case CMPLT_PC_DOUBLE:  
            case CMPLT_PC_DYNAMIC:
            case CMPLT_SF0:
            case CMPLT_SF1:
            case CMPLT_SF2:
            case CMPLT_SF3:
                break;
            default:
                return false;
            }
        }
        if (IS_FR(1) && IS_FR(2) && IS_FR(3) && IS_FR(4)) return true;
        break;
    case INST_FMIN:
    case INST_FMAX:
    case INST_FAMIN:
    case INST_FAMAX:
    case INST_FPMIN:
    case INST_FPMAX:
    case INST_FPAMIN:
    case INST_FPAMAX:
        for (U_32 i=0 ; IS_C(i) ; i++) {
            switch (C(i)) {
            case CMPLT_SF0:
            case CMPLT_SF1:
            case CMPLT_SF2:
            case CMPLT_SF3:
                break;
            default:
                return false;
            }
        }
        if (IS_FR(1) && IS_FR(2) && IS_FR(3)) return true;
        break;
    case INST_FPCMP:
        for (U_32 i=0 ; IS_C(i) ; i++) {
            switch (C(i)) {
            case CMPLT_SF0:
            case CMPLT_SF1:
            case CMPLT_SF2:
            case CMPLT_SF3:
            case CMPLT_FCMP_FREL_EQ:
            case CMPLT_FCMP_FREL_GT:
            case CMPLT_FCMP_FREL_LT:
            case CMPLT_FCMP_FREL_GE:
            case CMPLT_FCMP_FREL_LE:
            case CMPLT_FCMP_FREL_UNORD:
            case CMPLT_FCMP_FREL_NEQ:
            case CMPLT_FCMP_FREL_NGT:
            case CMPLT_FCMP_FREL_NLT:
            case CMPLT_FCMP_FREL_NGE:
            case CMPLT_FCMP_FREL_NLE:
            case CMPLT_FCMP_FREL_ORD:
                break;
            default:
                return false;
            }
        }
        if (IS_FR(1) && IS_FR(2) && IS_FR(3) && !IS_O(4)) return true;
        break;
    case INST_FMERGE_NS:
    case INST_FMERGE_S:
    case INST_FMERGE_SE:
        if (IS_FR(1) && IS_FR(2) && IS_FR(3) && !IS_O(4)) return true;
        break;
    case INST_FNEG:
        if (IS_FR(1) && IS_FR(2) && !IS_O(3) && !IS_C(0)) return true;
        break;
    case INST_FNMA:
        for ( U_32 i=0 ; IS_C(i) ; i++ ) {
            switch(C(i)) {
            case CMPLT_PC_SINGLE:
            case CMPLT_PC_DOUBLE:
            case CMPLT_PC_DYNAMIC:
            case CMPLT_SF0:
            case CMPLT_SF1:
            case CMPLT_SF2:
            case CMPLT_SF3:
                break;
            default:
                return false;
            }
        }
        if (IS_FR(1) && IS_FR(2) && IS_FR(3) && IS_FR(4) && !IS_O(5)) return true;
        break;
    case INST_FNORM:
        for ( U_32 i=0 ; IS_C(i) ; i++ ) {
            switch(C(i)) {
            case CMPLT_PC_SINGLE:
            case CMPLT_PC_DOUBLE:
            case CMPLT_PC_DYNAMIC:
            case CMPLT_SF0:
            case CMPLT_SF1:
            case CMPLT_SF2:
            case CMPLT_SF3:
                break;
            default:
                return false;
            }
        }
        if (IS_FR(1) && IS_FR(2) && !IS_FR(3)) return true;
        break;
    case INST_FSUB:
        if (IS_FR(1) && IS_FR(2) && IS_FR(3) && !IS_O(4) && !IS_C(2)) return true;
        break;
    case INST_FRCPA:
        if ( IS_C(0) ) {
            switch(C(0)) {
            case CMPLT_SF0:
            case CMPLT_SF1:
            case CMPLT_SF2:
            case CMPLT_SF3:
                break;
            default: 
                return false;
            }
        }
        if (IS_FR(1) && IS_PR(2) && IS_FR(3) && IS_FR(4) && !IS_O(5)) return true;
        break;
    case INST_GETF_S:
    case INST_GETF_D:
    case INST_GETF_EXP:
    case INST_GETF_SIG:
        if (IS_GR(1) && IS_FR(2) && !IS_O(3)) return true;
        break;
    case INST_LD:
    case INST_LD16:
    case INST_LD16_ACQ:
    case INST_LD8_FILL:
        return ldx(res, inst, icode, opnds, cmpls);
    case INST_LDF:
    case INST_LDF8:
    case INST_LDF_FILL:
        return ldfx(res, inst, icode, opnds, cmpls);
    case INST_MOV:
    case INST_MOV_I:                 
    case INST_MOV_M:
    case INST_MOV_RET:
        return mov(res, inst, icode, opnds, cmpls);
    case INST_MOVL:
        if (IS_GR(1) && IS_IMM64(2)) return true;
        break;
    case INST_SETF_S:
    case INST_SETF_D:
    case INST_SETF_EXP:
    case INST_SETF_SIG:
        if (!IS_O(3) && !IS_C(0) && IS_FR(1) && IS_GR(2)) return true;
        break;
    case INST_SHL:
    case INST_SHR:
    case INST_SHR_U:
        if (!IS_C(0) && !IS_O(4) && IS_GR(1) && IS_GR(2) 
            && (IS_GR(3) || (IS_IMM(3) && (V(3)&0x3F)==V(3)))) return true;
        break;
    case INST_SHLADD:
        if (V(3)>4 || V(3)<1) { res->append("shift value must be 1...4"); return false; }
        if (!IS_C(0) && !IS_O(5) && IS_GR(1) && IS_GR(2) && IS_GR(4)) return true;
        break;
    case INST_ST: 
    case INST_ST8_SPILL:
    case INST_ST16:
        return stx(res, inst, icode, opnds, cmpls);
    case INST_STF:
    case INST_STF8:
    case INST_STF_SPILL:
        for (uint64 i=0 ; IS_C(i) ; i++) {
            switch (C(i)) {
            case CMPLT_FSZ_D:
            case CMPLT_FSZ_E:
            case CMPLT_FSZ_S:
                if (icode==INST_STF && i!=0) return false;
                break;
            case CMPLT_HINT_NONE:
            case CMPLT_HINT_NTA: 
                if (icode!=INST_STF && i!=0) return false;
                break;
            default:
                return false;
            }
        }
        if (!IS_C(2) && IS_GR(1) && IS_FR(2) && (!IS_O(3) || IS_IMM9(3))) return true;
        break;
    case INST_SXT:
    case INST_ZXT:
        if (!IS_C(0)) return false;
        switch (C(0)) {
        case CMPLT_XSZ_1:
        case CMPLT_XSZ_2:
        case CMPLT_XSZ_4: 
            break;
        default: 
            return false;
        }
        if (!IS_C(1) && IS_GR(1) && IS_GR(2)) return true;
        break;
    case INST_DEF:
    case INST_USE:
        return true;
    case INST_XMA_L:
    case INST_XMA_LU:
    case INST_XMA_H:
    case INST_XMA_HU:
        if (!IS_C(0) && IS_FR(1) && IS_FR(2) && IS_FR(3) && IS_FR(4)) return true;
        break;
    
    default:
        IPF_ERR << ": NOT YET IMPLEMENTED VERIFIER FOR INSTRUCTION: " 
                << IrPrinter::toString(inst) << "\n";
        return true;;
    }