summaryrefslogtreecommitdiff
path: root/src/jit/emitxarch.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/jit/emitxarch.cpp')
-rw-r--r--src/jit/emitxarch.cpp79
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)
{