diff options
Diffstat (limited to 'src/jit/emitxarch.cpp')
-rw-r--r-- | src/jit/emitxarch.cpp | 79 |
1 files changed, 33 insertions, 46 deletions
diff --git a/src/jit/emitxarch.cpp b/src/jit/emitxarch.cpp index b6bacfa520..be5cefbfea 100644 --- a/src/jit/emitxarch.cpp +++ b/src/jit/emitxarch.cpp @@ -57,10 +57,6 @@ bool emitter::IsAVXInstruction(instruction ins) #endif } -#ifdef _TARGET_AMD64_ -#define REX_PREFIX_MASK 0xFF00000000LL -#endif // _TARGET_AMD64_ - #ifdef FEATURE_AVX_SUPPORT // Returns true if the AVX instruction is a binary operator that requires 3 operands. // When we emit an instruction with only two operands, we will duplicate the destination @@ -717,12 +713,10 @@ unsigned emitter::emitGetPrefixSize(code_t code) return 3; } -#ifdef _TARGET_AMD64_ - if (code & REX_PREFIX_MASK) + if (hasRexPrefix(code)) { return 1; } -#endif // _TARGET_AMD64_ return 0; } @@ -898,7 +892,8 @@ bool emitter::emitInsCanOnlyWriteSSE2OrAVXReg(instrDesc* id) // The following SSE2 instructions write to a general purpose integer register. if (!IsSSEOrAVXInstruction(ins) || ins == INS_mov_xmm2i || ins == INS_cvttsd2si #ifndef LEGACY_BACKEND - || ins == INS_cvttss2si || ins == INS_cvtsd2si || ins == INS_cvtss2si + || ins == INS_cvttss2si || ins == INS_cvtsd2si || ins == INS_cvtss2si || ins == INS_pmovmskb || + ins == INS_pextrw #endif // !LEGACY_BACKEND ) { @@ -1881,10 +1876,9 @@ UNATIVE_OFFSET emitter::emitInsSizeAM(instrDesc* id, code_t code) } } -#ifdef _TARGET_AMD64_ size += emitGetVexPrefixAdjustedSize(ins, attrSize, code); - if (code & REX_PREFIX_MASK) + if (hasRexPrefix(code)) { // REX prefix size += emitGetRexPrefixSize(ins); @@ -1899,7 +1893,6 @@ UNATIVE_OFFSET emitter::emitInsSizeAM(instrDesc* id, code_t code) // Should have a REX byte size += emitGetRexPrefixSize(ins); } -#endif // _TARGET_AMD64_ if (rgx == REG_NA) { @@ -2302,9 +2295,7 @@ void emitter::emitIns(instruction ins) } #endif // DEBUG -#ifdef _TARGET_AMD64_ - assert((code & REX_PREFIX_MASK) == 0); // Can't have a REX bit with no operands, right? -#endif // _TARGET_AMD64_ + assert(!hasRexPrefix(code)); // Can't have a REX bit with no operands, right? if (code & 0xFF000000) { @@ -2786,20 +2777,19 @@ CORINFO_FIELD_HANDLE emitter::emitFltOrDblConst(GenTreeDblCon* tree, emitAttr at regNumber emitter::emitInsBinary(instruction ins, emitAttr attr, GenTree* dst, GenTree* src) { // dst can only be a reg or modrm - assert(!dst->isContained() || dst->isContainedMemoryOp() || - instrIs3opImul(ins)); // dst on these isn't really the dst + assert(!dst->isContained() || dst->isUsedFromMemory() || instrIs3opImul(ins)); // dst on these isn't really the dst #ifdef DEBUG // src can be anything but both src and dst cannot be addr modes // or at least cannot be contained addr modes - if (dst->isContainedMemoryOp()) + if (dst->isUsedFromMemory()) { - assert(!src->isContainedMemoryOp()); + assert(!src->isUsedFromMemory()); } - if (src->isContainedMemoryOp()) + if (src->isUsedFromMemory()) { - assert(!dst->isContainedMemoryOp()); + assert(!dst->isUsedFromMemory()); } #endif @@ -2837,7 +2827,7 @@ regNumber emitter::emitInsBinary(instruction ins, emitAttr attr, GenTree* dst, G // find local field if any GenTreeLclFld* lclField = nullptr; - if (src->isContainedLclField()) + if (src->isLclFldUsedFromMemory()) { lclField = src->AsLclFld(); } @@ -2848,12 +2838,12 @@ regNumber emitter::emitInsBinary(instruction ins, emitAttr attr, GenTree* dst, G // find contained lcl var if any GenTreeLclVar* lclVar = nullptr; - if (src->isContainedLclVar()) + if (src->isLclVarUsedFromMemory()) { assert(src->IsRegOptional()); lclVar = src->AsLclVar(); } - else if (dst->isContainedLclVar()) + if (dst->isLclVarUsedFromMemory()) { assert(dst->IsRegOptional()); lclVar = dst->AsLclVar(); @@ -2861,12 +2851,12 @@ regNumber emitter::emitInsBinary(instruction ins, emitAttr attr, GenTree* dst, G // find contained spill tmp if any TempDsc* tmpDsc = nullptr; - if (src->isContainedSpillTemp()) + if (src->isUsedFromSpillTemp()) { assert(src->IsRegOptional()); tmpDsc = codeGen->getSpillTempDsc(src); } - else if (dst->isContainedSpillTemp()) + else if (dst->isUsedFromSpillTemp()) { assert(dst->IsRegOptional()); tmpDsc = codeGen->getSpillTempDsc(dst); @@ -2952,7 +2942,7 @@ regNumber emitter::emitInsBinary(instruction ins, emitAttr attr, GenTree* dst, G if (varNum != BAD_VAR_NUM || tmpDsc != nullptr) { // Is the memory op in the source position? - if (src->isContainedMemoryOp()) + if (src->isUsedFromMemory()) { if (instrHasImplicitRegPairDest(ins)) { @@ -3997,16 +3987,14 @@ void emitter::emitIns_C_I(instruction ins, emitAttr attr, CORINFO_FIELD_HANDLE f code_t code = insCodeMI(ins); UNATIVE_OFFSET sz = emitInsSizeCV(id, code, val); -#ifdef _TARGET_AMD64_ // Vex prefix sz += emitGetVexPrefixAdjustedSize(ins, attr, insCodeMI(ins)); // REX prefix, if not already included in "code" - if (TakesRexWPrefix(ins, attr) && (code & REX_PREFIX_MASK) == 0) + if (TakesRexWPrefix(ins, attr) && !hasRexPrefix(code)) { sz += emitGetRexPrefixSize(ins); } -#endif // _TARGET_AMD64_ id->idAddr()->iiaFieldHnd = fldHnd; id->idCodeSize(sz); @@ -8055,10 +8043,7 @@ DONE: } else { - if (emitInsCanOnlyWriteSSE2OrAVXReg(id)) - { - } - else + if (!emitInsCanOnlyWriteSSE2OrAVXReg(id)) { switch (id->idInsFmt()) { @@ -8450,10 +8435,7 @@ BYTE* emitter::emitOutputSV(BYTE* dst, instrDesc* id, code_t code, CnsVal* addc) } else { - if (emitInsCanOnlyWriteSSE2OrAVXReg(id)) - { - } - else + if (!emitInsCanOnlyWriteSSE2OrAVXReg(id)) { switch (id->idInsFmt()) { @@ -8883,10 +8865,7 @@ BYTE* emitter::emitOutputCV(BYTE* dst, instrDesc* id, code_t code, CnsVal* addc) } else { - if (emitInsCanOnlyWriteSSE2OrAVXReg(id)) - { - } - else + if (!emitInsCanOnlyWriteSSE2OrAVXReg(id)) { switch (id->idInsFmt()) { @@ -9428,10 +9407,7 @@ BYTE* emitter::emitOutputRR(BYTE* dst, instrDesc* id) } else { - if (emitInsCanOnlyWriteSSE2OrAVXReg(id)) - { - } - else + if (!emitInsCanOnlyWriteSSE2OrAVXReg(id)) { switch (id->idInsFmt()) { @@ -10832,6 +10808,12 @@ size_t emitter::emitOutputInstr(insGroup* ig, instrDesc* id, BYTE** dp) dst += emitOutputByte(dst, emitGetInsSC(id)); sz = emitSizeOfInsDsc(id); + + // Kill any GC ref in the destination register if necessary. + if (!emitInsCanOnlyWriteSSE2OrAVXReg(id)) + { + emitGCregDeadUpd(id->idReg1(), dst); + } break; /********************************************************************/ @@ -11202,9 +11184,14 @@ size_t emitter::emitOutputInstr(insGroup* ig, instrDesc* id, BYTE** dp) assert(sz == emitSizeOfInsDsc(id)); #if !FEATURE_FIXED_OUT_ARGS + bool updateStackLevel = !emitIGisInProlog(ig) && !emitIGisInEpilog(ig); + +#if FEATURE_EH_FUNCLETS + updateStackLevel = updateStackLevel && !emitIGisInFuncletProlog(ig) && !emitIGisInFuncletEpilog(ig); +#endif // FEATURE_EH_FUNCLETS // Make sure we keep the current stack level up to date - if (!emitIGisInProlog(ig) && !emitIGisInEpilog(ig)) + if (updateStackLevel) { switch (ins) { |