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;;
}