summaryrefslogtreecommitdiff
path: root/src/jit/emitxarch.cpp
diff options
context:
space:
mode:
authorTanner Gooding <tagoo@outlook.com>2018-01-12 20:47:07 -0800
committerTanner Gooding <tagoo@outlook.com>2018-01-16 16:30:10 -0800
commit5ca94174d1d20755ef40e0a559becb6794b9bf74 (patch)
treed306f2727191cdf021d59b55d089be03112d0424 /src/jit/emitxarch.cpp
parenta15aa12827471776801fb87a4bccd69d8d64502c (diff)
downloadcoreclr-5ca94174d1d20755ef40e0a559becb6794b9bf74.tar.gz
coreclr-5ca94174d1d20755ef40e0a559becb6794b9bf74.tar.bz2
coreclr-5ca94174d1d20755ef40e0a559becb6794b9bf74.zip
Updating most of the SSE Compare intrinsics to support containment
Diffstat (limited to 'src/jit/emitxarch.cpp')
-rw-r--r--src/jit/emitxarch.cpp341
1 files changed, 297 insertions, 44 deletions
diff --git a/src/jit/emitxarch.cpp b/src/jit/emitxarch.cpp
index f380abb447..8881092940 100644
--- a/src/jit/emitxarch.cpp
+++ b/src/jit/emitxarch.cpp
@@ -2597,12 +2597,16 @@ emitter::insFormat emitter::emitMapFmtAtoM(insFormat fmt)
return IF_RRD_MRD;
case IF_RWR_ARD:
return IF_RWR_MRD;
+ case IF_RWR_ARD_CNS:
+ return IF_RWR_MRD_CNS;
case IF_RRW_ARD:
return IF_RRW_MRD;
case IF_RRW_ARD_CNS:
return IF_RRW_MRD_CNS;
case IF_RWR_RRD_ARD:
return IF_RWR_RRD_MRD;
+ case IF_RWR_RRD_ARD_CNS:
+ return IF_RWR_RRD_MRD_CNS;
case IF_ARD_RRD:
return IF_MRD_RRD;
@@ -3926,13 +3930,16 @@ void emitter::emitIns_R_A_I(instruction ins, emitAttr attr, regNumber reg1, GenT
{
noway_assert(emitVerifyEncodable(ins, EA_SIZE(attr), reg1));
+ assert(IsSSEOrAVXInstruction(ins));
+ assert(IsThreeOperandAVXInstruction(ins));
+
ssize_t offs = indir->Offset();
instrDesc* id = emitNewInstrAmdCns(attr, offs, ival);
id->idIns(ins);
id->idReg1(reg1);
- emitHandleMemOp(indir, id, IF_RRW_ARD_CNS, ins);
+ emitHandleMemOp(indir, id, IF_RWR_ARD_CNS, ins);
// Plus one for the 1-byte immediate (ival)
UNATIVE_OFFSET sz = emitInsSizeAM(id, insCodeRM(ins)) + emitGetVexPrefixAdjustedSize(ins, attr, insCodeRM(ins)) + 1;
@@ -3945,35 +3952,26 @@ void emitter::emitIns_R_A_I(instruction ins, emitAttr attr, regNumber reg1, GenT
void emitter::emitIns_R_C_I(
instruction ins, emitAttr attr, regNumber reg1, CORINFO_FIELD_HANDLE fldHnd, int offs, int ival)
{
+ noway_assert(emitVerifyEncodable(ins, EA_SIZE(attr), reg1));
+
+ assert(IsSSEOrAVXInstruction(ins));
+ assert(IsThreeOperandAVXInstruction(ins));
+
// Static always need relocs
if (!jitStaticFldIsGlobAddr(fldHnd))
{
attr = EA_SET_FLG(attr, EA_DSP_RELOC_FLG);
}
- noway_assert(emitVerifyEncodable(ins, EA_SIZE(attr), reg1));
-
instrDesc* id = emitNewInstrCnsDsp(attr, ival, offs);
- UNATIVE_OFFSET sz = emitInsSizeCV(id, insCodeRM(ins));
-
- // Plus one for the 1 byte immediate (ival)
- sz += 1;
-
- // VEX prefix
- sz += emitGetVexPrefixAdjustedSize(ins, attr, insCodeRM(ins));
-
- // REX prefix
- if (IsExtendedReg(reg1, attr))
- {
- sz += emitGetRexPrefixSize(ins);
- }
+ UNATIVE_OFFSET sz = emitInsSizeCV(id, insCodeRM(ins)) + emitGetVexPrefixAdjustedSize(ins, attr, insCodeRM(ins)) + 1;
id->idIns(ins);
- id->idInsFmt(IF_RRW_MRD_CNS);
+ id->idInsFmt(IF_RWR_RRD_MRD_CNS);
id->idReg1(reg1);
id->idAddr()->iiaFieldHnd = fldHnd;
- id->idCodeSize(sz);
+ id->idCodeSize(sz);
dispIns(id);
emitCurIGsize += sz;
}
@@ -3982,30 +3980,24 @@ void emitter::emitIns_R_S_I(instruction ins, emitAttr attr, regNumber reg1, int
{
noway_assert(emitVerifyEncodable(ins, EA_SIZE(attr), reg1));
- instrDesc* id = emitNewInstrCns(attr, ival);
- UNATIVE_OFFSET sz = emitInsSizeSV(insCodeRM(ins), varx, offs);
-
- // Plus one for the 1 byte immediate (ival)
- sz += 1;
-
- // VEX prefix
- sz += emitGetVexPrefixAdjustedSize(ins, attr, insCodeRM(ins));
+ assert(IsSSEOrAVXInstruction(ins));
+ assert(IsThreeOperandAVXInstruction(ins));
- // REX prefix
- if (IsExtendedReg(reg1, attr))
- {
- sz += emitGetRexPrefixSize(ins);
- }
+ instrDesc* id = emitNewInstrCns(attr, ival);
+ UNATIVE_OFFSET sz =
+ emitInsSizeSV(insCodeRM(ins), varx, offs) + emitGetVexPrefixAdjustedSize(ins, attr, insCodeRM(ins)) + 1;
id->idIns(ins);
- id->idInsFmt(IF_RRW_SRD_CNS);
+ id->idInsFmt(IF_RWR_RRD_SRD_CNS);
id->idReg1(reg1);
id->idAddr()->iiaLclVar.initLclVarAddr(varx, offs);
- id->idCodeSize(sz);
+
#ifdef DEBUG
id->idDebugOnlyInfo()->idVarRefOffs = emitVarRefOffs;
#endif
+ id->idCodeSize(sz);
+
dispIns(id);
emitCurIGsize += sz;
}
@@ -4110,6 +4102,54 @@ void emitter::emitIns_R_R_S(instruction ins, emitAttr attr, regNumber reg1, regN
emitCurIGsize += sz;
}
+void emitter::emitIns_R_R_A_I(
+ instruction ins, emitAttr attr, regNumber reg1, regNumber reg2, GenTreeIndir* indir, int ival, insFormat fmt)
+{
+ assert(IsSSEOrAVXInstruction(ins));
+ assert(IsThreeOperandAVXInstruction(ins));
+
+ ssize_t offs = indir->Offset();
+ instrDesc* id = emitNewInstrAmdCns(attr, offs, ival);
+
+ id->idIns(ins);
+ id->idReg1(reg1);
+ id->idReg2(reg2);
+
+ emitHandleMemOp(indir, id, fmt, ins);
+
+ UNATIVE_OFFSET sz = emitInsSizeAM(id, insCodeRM(ins)) + emitGetVexPrefixAdjustedSize(ins, attr, insCodeRM(ins)) + 1;
+ id->idCodeSize(sz);
+
+ dispIns(id);
+ emitCurIGsize += sz;
+}
+
+void emitter::emitIns_R_R_C_I(
+ instruction ins, emitAttr attr, regNumber reg1, regNumber reg2, CORINFO_FIELD_HANDLE fldHnd, int offs, int ival)
+{
+ assert(IsSSEOrAVXInstruction(ins));
+ assert(IsThreeOperandAVXInstruction(ins));
+
+ // Static always need relocs
+ if (!jitStaticFldIsGlobAddr(fldHnd))
+ {
+ attr = EA_SET_FLG(attr, EA_DSP_RELOC_FLG);
+ }
+
+ instrDesc* id = emitNewInstrCnsDsp(attr, ival, offs);
+ UNATIVE_OFFSET sz = emitInsSizeCV(id, insCodeRM(ins)) + emitGetVexPrefixAdjustedSize(ins, attr, insCodeRM(ins)) + 1;
+
+ id->idIns(ins);
+ id->idInsFmt(IF_RWR_RRD_MRD_CNS);
+ id->idReg1(reg1);
+ id->idReg2(reg2);
+ id->idAddr()->iiaFieldHnd = fldHnd;
+
+ id->idCodeSize(sz);
+ dispIns(id);
+ emitCurIGsize += sz;
+}
+
/**********************************************************************************
* emitIns_R_R_R_I: Add an instruction with three register operands and an immediate.
*
@@ -4144,6 +4184,31 @@ void emitter::emitIns_R_R_R_I(
emitCurIGsize += sz;
}
+void emitter::emitIns_R_R_S_I(
+ instruction ins, emitAttr attr, regNumber reg1, regNumber reg2, int varx, int offs, int ival)
+{
+ assert(IsSSEOrAVXInstruction(ins));
+ assert(IsThreeOperandAVXInstruction(ins));
+
+ instrDesc* id = emitNewInstrCns(attr, ival);
+ UNATIVE_OFFSET sz =
+ emitInsSizeSV(insCodeRM(ins), varx, offs) + emitGetVexPrefixAdjustedSize(ins, attr, insCodeRM(ins)) + 1;
+
+ id->idIns(ins);
+ id->idInsFmt(IF_RWR_RRD_SRD_CNS);
+ id->idReg1(reg1);
+ id->idReg2(reg2);
+ id->idAddr()->iiaLclVar.initLclVarAddr(varx, offs);
+
+#ifdef DEBUG
+ id->idDebugOnlyInfo()->idVarRefOffs = emitVarRefOffs;
+#endif
+
+ id->idCodeSize(sz);
+ dispIns(id);
+ emitCurIGsize += sz;
+}
+
/*****************************************************************************
*
* Add an instruction with a register + static member operands.
@@ -5101,7 +5166,7 @@ void emitter::emitIns_SIMD_R_R_A(
{
emitIns_R_R(INS_movaps, emitTypeSize(simdtype), reg, reg1);
}
- emitIns_R_A(ins, emitTypeSize(simdtype), reg, indir, IF_RRW_ARD);
+ emitIns_R_A(ins, emitTypeSize(simdtype), reg, indir, IF_RWR_ARD);
}
}
@@ -5154,6 +5219,40 @@ void emitter::emitIns_SIMD_R_R_S(instruction ins, regNumber reg, regNumber reg1,
}
}
+void emitter::emitIns_SIMD_R_R_A_I(
+ instruction ins, regNumber reg, regNumber reg1, GenTreeIndir* indir, int ival, var_types simdtype)
+{
+ if (UseVEXEncoding())
+ {
+ emitIns_R_R_A_I(ins, emitTypeSize(simdtype), reg, reg1, indir, ival, IF_RWR_RRD_ARD_CNS);
+ }
+ else
+ {
+ if (reg1 != reg)
+ {
+ emitIns_R_R(INS_movaps, emitTypeSize(simdtype), reg, reg1);
+ }
+ emitIns_R_A_I(ins, emitTypeSize(simdtype), reg, indir, ival);
+ }
+}
+
+void emitter::emitIns_SIMD_R_R_C_I(
+ instruction ins, regNumber reg, regNumber reg1, CORINFO_FIELD_HANDLE fldHnd, int offs, int ival, var_types simdtype)
+{
+ if (UseVEXEncoding())
+ {
+ emitIns_R_R_C_I(ins, emitTypeSize(simdtype), reg, reg1, fldHnd, offs, ival);
+ }
+ else
+ {
+ if (reg1 != reg)
+ {
+ emitIns_R_R(INS_movaps, emitTypeSize(simdtype), reg, reg1);
+ }
+ emitIns_R_C_I(ins, emitTypeSize(simdtype), reg, fldHnd, offs, ival);
+ }
+}
+
void emitter::emitIns_SIMD_R_R_R_I(
instruction ins, regNumber reg, regNumber reg1, regNumber reg2, int ival, var_types simdtype)
{
@@ -5170,6 +5269,23 @@ void emitter::emitIns_SIMD_R_R_R_I(
emitIns_R_R_I(ins, emitTypeSize(simdtype), reg, reg2, ival);
}
}
+
+void emitter::emitIns_SIMD_R_R_S_I(
+ instruction ins, regNumber reg, regNumber reg1, int varx, int offs, int ival, var_types simdtype)
+{
+ if (UseVEXEncoding())
+ {
+ emitIns_R_R_S_I(ins, emitTypeSize(simdtype), reg, reg1, varx, offs, ival);
+ }
+ else
+ {
+ if (reg1 != reg)
+ {
+ emitIns_R_R(INS_movaps, emitTypeSize(simdtype), reg, reg1);
+ }
+ emitIns_R_S_I(ins, emitTypeSize(simdtype), reg, varx, offs, ival);
+ }
+}
#endif
/*****************************************************************************
@@ -7185,14 +7301,15 @@ void emitter::emitDispIns(
emitDispAddrMode(id);
break;
- case IF_RRW_ARD_CNS:
+ case IF_RWR_ARD_CNS:
+ {
printf("%s, %s", emitRegName(id->idReg1(), attr), sstr);
emitDispAddrMode(id);
-
emitGetInsAmdCns(id, &cnsVal);
- val = cnsVal.cnsVal;
+ val = cnsVal.cnsVal;
printf(", ");
+
if (cnsVal.cnsReloc)
{
emitDispReloc(val);
@@ -7202,12 +7319,34 @@ void emitter::emitDispIns(
goto PRINT_CONSTANT;
}
break;
+ }
case IF_RWR_RRD_ARD:
printf("%s, %s, %s", emitRegName(id->idReg1(), attr), emitRegName(id->idReg2(), attr), sstr);
emitDispAddrMode(id);
break;
+ case IF_RWR_RRD_ARD_CNS:
+ {
+ printf("%s, %s, %s", emitRegName(id->idReg1(), attr), emitRegName(id->idReg2(), attr), sstr);
+ emitDispAddrMode(id);
+ emitGetInsAmdCns(id, &cnsVal);
+
+ val = cnsVal.cnsVal;
+ printf(", ");
+
+ if (cnsVal.cnsReloc)
+ {
+ emitDispReloc(val);
+ }
+ else
+ {
+ goto PRINT_CONSTANT;
+ }
+
+ break;
+ }
+
case IF_ARD_RRD:
case IF_AWR_RRD:
case IF_ARW_RRD:
@@ -7351,15 +7490,16 @@ void emitter::emitDispIns(
break;
- case IF_RRW_SRD_CNS:
+ case IF_RWR_SRD_CNS:
+ {
printf("%s, %s", emitRegName(id->idReg1(), attr), sstr);
emitDispFrameRef(id->idAddr()->iiaLclVar.lvaVarNum(), id->idAddr()->iiaLclVar.lvaOffset(),
id->idDebugOnlyInfo()->idVarRefOffs, asmfm);
-
emitGetInsCns(id, &cnsVal);
- val = cnsVal.cnsVal;
+ val = cnsVal.cnsVal;
printf(", ");
+
if (cnsVal.cnsReloc)
{
emitDispReloc(val);
@@ -7369,6 +7509,7 @@ void emitter::emitDispIns(
goto PRINT_CONSTANT;
}
break;
+ }
case IF_RWR_RRD_SRD:
printf("%s, %s, %s", emitRegName(id->idReg1(), attr), emitRegName(id->idReg2(), attr), sstr);
@@ -7376,6 +7517,27 @@ void emitter::emitDispIns(
id->idDebugOnlyInfo()->idVarRefOffs, asmfm);
break;
+ case IF_RWR_RRD_SRD_CNS:
+ {
+ printf("%s, %s, %s", emitRegName(id->idReg1(), attr), emitRegName(id->idReg2(), attr), sstr);
+ emitDispFrameRef(id->idAddr()->iiaLclVar.lvaVarNum(), id->idAddr()->iiaLclVar.lvaOffset(),
+ id->idDebugOnlyInfo()->idVarRefOffs, asmfm);
+ emitGetInsCns(id, &cnsVal);
+
+ val = cnsVal.cnsVal;
+ printf(", ");
+
+ if (cnsVal.cnsReloc)
+ {
+ emitDispReloc(val);
+ }
+ else
+ {
+ goto PRINT_CONSTANT;
+ }
+ break;
+ }
+
case IF_RRD_RRD:
case IF_RWR_RRD:
case IF_RRW_RRD:
@@ -7504,15 +7666,16 @@ void emitter::emitDispIns(
emitDispClsVar(id->idAddr()->iiaFieldHnd, offs, ID_INFO_DSP_RELOC);
break;
- case IF_RRW_MRD_CNS:
+ case IF_RWR_MRD_CNS:
+ {
printf("%s, %s", emitRegName(id->idReg1(), attr), sstr);
offs = emitGetInsDsp(id);
emitDispClsVar(id->idAddr()->iiaFieldHnd, offs, ID_INFO_DSP_RELOC);
-
emitGetInsDcmCns(id, &cnsVal);
- val = cnsVal.cnsVal;
+ val = cnsVal.cnsVal;
printf(", ");
+
if (cnsVal.cnsReloc)
{
emitDispReloc(val);
@@ -7522,6 +7685,7 @@ void emitter::emitDispIns(
goto PRINT_CONSTANT;
}
break;
+ }
case IF_RWR_RRD_MRD:
printf("%s, %s, %s", emitRegName(id->idReg1(), attr), emitRegName(id->idReg2(), attr), sstr);
@@ -7529,6 +7693,27 @@ void emitter::emitDispIns(
emitDispClsVar(id->idAddr()->iiaFieldHnd, offs, ID_INFO_DSP_RELOC);
break;
+ case IF_RWR_RRD_MRD_CNS:
+ {
+ printf("%s, %s, %s", emitRegName(id->idReg1(), attr), emitRegName(id->idReg2(), attr), sstr);
+ offs = emitGetInsDsp(id);
+ emitDispClsVar(id->idAddr()->iiaFieldHnd, offs, ID_INFO_DSP_RELOC);
+ emitGetInsDcmCns(id, &cnsVal);
+
+ val = cnsVal.cnsVal;
+ printf(", ");
+
+ if (cnsVal.cnsReloc)
+ {
+ emitDispReloc(val);
+ }
+ else
+ {
+ goto PRINT_CONSTANT;
+ }
+ break;
+ }
+
case IF_RWR_MRD_OFF:
printf("%s, %s", emitRegName(id->idReg1(), attr), "offset");
@@ -7980,7 +8165,7 @@ BYTE* emitter::emitOutputAM(BYTE* dst, instrDesc* id, code_t code, CnsVal* addc)
{
regNumber src1 = id->idReg2();
- if (id->idInsFmt() != IF_RWR_RRD_ARD)
+ if ((id->idInsFmt() != IF_RWR_RRD_ARD) && (id->idInsFmt() != IF_RWR_RRD_ARD_CNS))
{
src1 = id->idReg1();
}
@@ -11549,6 +11734,18 @@ size_t emitter::emitOutputInstr(insGroup* ig, instrDesc* id, BYTE** dp)
sz = emitSizeOfInsDsc(id);
break;
+ case IF_RWR_ARD_CNS:
+ case IF_RWR_RRD_ARD_CNS:
+ {
+ emitGetInsAmdCns(id, &cnsVal);
+ code = insCodeRM(ins);
+ code = AddVexPrefixIfNeeded(ins, code, size);
+ regcode = (insEncodeReg345(ins, id->idReg1(), size, &code) << 8);
+ dst = emitOutputAM(dst, id, code | regcode, &cnsVal);
+ sz = emitSizeOfInsDsc(id);
+ break;
+ }
+
case IF_ARD_RRD:
case IF_AWR_RRD:
case IF_ARW_RRD:
@@ -11699,6 +11896,34 @@ size_t emitter::emitOutputInstr(insGroup* ig, instrDesc* id, BYTE** dp)
}
break;
+ case IF_RWR_SRD_CNS:
+ case IF_RWR_RRD_SRD_CNS:
+ {
+ emitGetInsCns(id, &cnsVal);
+ code = insCodeRM(ins);
+
+ // 4-byte AVX instructions are special cased inside emitOutputSV
+ // since they do not have space to encode ModRM byte.
+ if (Is4ByteAVXInstruction(ins))
+ {
+ dst = emitOutputSV(dst, id, code, &cnsVal);
+ }
+ else
+ {
+ code = AddVexPrefixIfNeeded(ins, code, size);
+
+ if (IsDstDstSrcAVXInstruction(ins))
+ {
+ // encode source operand reg in 'vvvv' bits in 1's compliement form
+ code = insEncodeReg3456(ins, id->idReg1(), size, code);
+ }
+
+ regcode = (insEncodeReg345(ins, id->idReg1(), size, &code) << 8);
+ dst = emitOutputSV(dst, id, code | regcode, &cnsVal);
+ }
+ break;
+ }
+
case IF_SRD_RRD:
case IF_SWR_RRD:
case IF_SRW_RRD:
@@ -11815,6 +12040,34 @@ size_t emitter::emitOutputInstr(insGroup* ig, instrDesc* id, BYTE** dp)
sz = emitSizeOfInsDsc(id);
break;
+ case IF_RWR_MRD_CNS:
+ case IF_RWR_RRD_MRD_CNS:
+ {
+ emitGetInsCns(id, &cnsVal);
+ code = insCodeRM(ins);
+
+ // Special case 4-byte AVX instructions
+ if (Is4ByteAVXInstruction(ins))
+ {
+ dst = emitOutputCV(dst, id, code, &cnsVal);
+ }
+ else
+ {
+ code = AddVexPrefixIfNeeded(ins, code, size);
+
+ if (IsDstDstSrcAVXInstruction(ins))
+ {
+ // encode source operand reg in 'vvvv' bits in 1's compliement form
+ code = insEncodeReg3456(ins, id->idReg1(), size, code);
+ }
+
+ regcode = (insEncodeReg345(ins, id->idReg1(), size, &code) << 8);
+ dst = emitOutputCV(dst, id, code | regcode | 0x0500, &cnsVal);
+ }
+ sz = emitSizeOfInsDsc(id);
+ break;
+ }
+
case IF_RWR_MRD_OFF:
code = insCode(ins);
code = AddVexPrefixIfNeeded(ins, code, size);