@@ -1998,8 +1998,8 @@ UNATIVE_OFFSET emitter::emitInsSizeAM(instrDesc* id, code_t code)
1998
1998
// BT supports 16 bit operands and this code doesn't handle the necessary 66 prefix.
1999
1999
assert (ins != INS_bt);
2000
2000
2001
- assert ((attrSize == EA_4BYTE) || (attrSize == EA_PTRSIZE) // Only for x64
2002
- || (attrSize == EA_16BYTE) // only for x64
2001
+ assert ((attrSize == EA_4BYTE) || (attrSize == EA_PTRSIZE) // Only for x64
2002
+ || (attrSize == EA_16BYTE) || (attrSize == EA_32BYTE) // only for x64
2003
2003
|| (ins == INS_movzx) || (ins == INS_movsx));
2004
2004
size = 3 ;
2005
2005
}
@@ -2588,6 +2588,8 @@ emitter::insFormat emitter::emitMapFmtAtoM(insFormat fmt)
2588
2588
return IF_RWR_MRD;
2589
2589
case IF_RRW_ARD:
2590
2590
return IF_RRW_MRD;
2591
+ case IF_RWR_RRD_ARD:
2592
+ return IF_RWR_RRD_MRD;
2591
2593
2592
2594
case IF_ARD_RRD:
2593
2595
return IF_MRD_RRD;
@@ -3889,6 +3891,71 @@ void emitter::emitIns_R_R_I(instruction ins, emitAttr attr, regNumber reg1, regN
3889
3891
emitCurIGsize += sz;
3890
3892
}
3891
3893
3894
+ void emitter::emitIns_R_A (instruction ins, emitAttr attr, regNumber reg1, GenTreeIndir* indir, insFormat fmt)
3895
+ {
3896
+ ssize_t offs = indir->Offset ();
3897
+ instrDesc* id = emitNewInstrAmd (attr, offs);
3898
+
3899
+ id->idIns (ins);
3900
+ id->idReg1 (reg1);
3901
+
3902
+ emitHandleMemOp (indir, id, fmt, ins);
3903
+
3904
+ UNATIVE_OFFSET sz = emitInsSizeAM (id, insCodeRM (ins));
3905
+ id->idCodeSize (sz);
3906
+
3907
+ dispIns (id);
3908
+ emitCurIGsize += sz;
3909
+ }
3910
+
3911
+ void emitter::emitIns_R_R_A (
3912
+ instruction ins, emitAttr attr, regNumber reg1, regNumber reg2, GenTreeIndir* indir, insFormat fmt)
3913
+ {
3914
+ assert (IsSSEOrAVXInstruction (ins));
3915
+ assert (IsThreeOperandAVXInstruction (ins));
3916
+
3917
+ ssize_t offs = indir->Offset ();
3918
+ instrDesc* id = emitNewInstrAmd (attr, offs);
3919
+
3920
+ id->idIns (ins);
3921
+ id->idReg1 (reg1);
3922
+ id->idReg2 (reg2);
3923
+
3924
+ emitHandleMemOp (indir, id, fmt, ins);
3925
+
3926
+ UNATIVE_OFFSET sz = emitInsSizeAM (id, insCodeRM (ins)) + emitGetVexPrefixAdjustedSize (ins, attr, insCodeRM (ins));
3927
+ id->idCodeSize (sz);
3928
+
3929
+ dispIns (id);
3930
+ emitCurIGsize += sz;
3931
+ }
3932
+
3933
+ void emitter::emitIns_R_R_C (
3934
+ instruction ins, emitAttr attr, regNumber reg1, regNumber reg2, CORINFO_FIELD_HANDLE fldHnd, int offs)
3935
+ {
3936
+ assert (IsSSEOrAVXInstruction (ins));
3937
+ assert (IsThreeOperandAVXInstruction (ins));
3938
+
3939
+ // Static always need relocs
3940
+ if (!jitStaticFldIsGlobAddr (fldHnd))
3941
+ {
3942
+ attr = EA_SET_FLG (attr, EA_DSP_RELOC_FLG);
3943
+ }
3944
+
3945
+ instrDesc* id = emitNewInstrDsp (attr, offs);
3946
+ UNATIVE_OFFSET sz = emitInsSizeCV (id, insCodeRM (ins)) + emitGetVexPrefixAdjustedSize (ins, attr, insCodeRM (ins));
3947
+
3948
+ id->idIns (ins);
3949
+ id->idInsFmt (IF_RWR_RRD_MRD);
3950
+ id->idReg1 (reg1);
3951
+ id->idReg2 (reg2);
3952
+ id->idAddr ()->iiaFieldHnd = fldHnd;
3953
+
3954
+ id->idCodeSize (sz);
3955
+ dispIns (id);
3956
+ emitCurIGsize += sz;
3957
+ }
3958
+
3892
3959
/* ****************************************************************************
3893
3960
*
3894
3961
* Add an instruction with three register operands.
@@ -3915,6 +3982,30 @@ void emitter::emitIns_R_R_R(instruction ins, emitAttr attr, regNumber targetReg,
3915
3982
emitCurIGsize += sz;
3916
3983
}
3917
3984
3985
+ void emitter::emitIns_R_R_S (instruction ins, emitAttr attr, regNumber reg1, regNumber reg2, int varx, int offs)
3986
+ {
3987
+ assert (IsSSEOrAVXInstruction (ins));
3988
+ assert (IsThreeOperandAVXInstruction (ins));
3989
+
3990
+ instrDesc* id = emitNewInstr (attr);
3991
+ UNATIVE_OFFSET sz =
3992
+ emitInsSizeSV (insCodeRM (ins), varx, offs) + emitGetVexPrefixAdjustedSize (ins, attr, insCodeRM (ins));
3993
+
3994
+ id->idIns (ins);
3995
+ id->idInsFmt (IF_RWR_RRD_SRD);
3996
+ id->idReg1 (reg1);
3997
+ id->idReg2 (reg2);
3998
+ id->idAddr ()->iiaLclVar .initLclVarAddr (varx, offs);
3999
+
4000
+ #ifdef DEBUG
4001
+ id->idDebugOnlyInfo ()->idVarRefOffs = emitVarRefOffs;
4002
+ #endif
4003
+
4004
+ id->idCodeSize (sz);
4005
+ dispIns (id);
4006
+ emitCurIGsize += sz;
4007
+ }
4008
+
3918
4009
/* *********************************************************************************
3919
4010
* emitIns_R_R_R_I: Add an instruction with three register operands and an immediate.
3920
4011
*
@@ -4888,9 +4979,43 @@ void emitter::emitIns_AX_R(instruction ins, emitAttr attr, regNumber ireg, regNu
4888
4979
}
4889
4980
4890
4981
#if FEATURE_HW_INTRINSICS
4982
+ void emitter::emitIns_SIMD_R_R_A (
4983
+ instruction ins, regNumber reg, regNumber reg1, GenTreeIndir* indir, var_types simdtype)
4984
+ {
4985
+ if (UseVEXEncoding ())
4986
+ {
4987
+ emitIns_R_R_A (ins, emitTypeSize (simdtype), reg, reg1, indir, IF_RWR_RRD_ARD);
4988
+ }
4989
+ else
4990
+ {
4991
+ if (reg1 != reg)
4992
+ {
4993
+ emitIns_R_R (INS_movaps, emitTypeSize (simdtype), reg, reg1);
4994
+ }
4995
+ emitIns_R_A (ins, emitTypeSize (simdtype), reg, indir, IF_RRW_ARD);
4996
+ }
4997
+ }
4998
+
4999
+ void emitter::emitIns_SIMD_R_R_C (
5000
+ instruction ins, regNumber reg, regNumber reg1, CORINFO_FIELD_HANDLE fldHnd, int offs, var_types simdtype)
5001
+ {
5002
+ if (UseVEXEncoding ())
5003
+ {
5004
+ emitIns_R_R_C (ins, emitTypeSize (simdtype), reg, reg1, fldHnd, offs);
5005
+ }
5006
+ else
5007
+ {
5008
+ if (reg1 != reg)
5009
+ {
5010
+ emitIns_R_R (INS_movaps, emitTypeSize (simdtype), reg, reg1);
5011
+ }
5012
+ emitIns_R_C (ins, emitTypeSize (simdtype), reg, fldHnd, offs);
5013
+ }
5014
+ }
5015
+
4891
5016
void emitter::emitIns_SIMD_R_R_R (instruction ins, regNumber reg, regNumber reg1, regNumber reg2, var_types simdtype)
4892
5017
{
4893
- if (UseVEXEncoding () && reg1 != reg )
5018
+ if (UseVEXEncoding ())
4894
5019
{
4895
5020
emitIns_R_R_R (ins, emitTypeSize (simdtype), reg, reg1, reg2);
4896
5021
}
@@ -4903,6 +5028,22 @@ void emitter::emitIns_SIMD_R_R_R(instruction ins, regNumber reg, regNumber reg1,
4903
5028
emitIns_R_R (ins, emitTypeSize (simdtype), reg, reg2);
4904
5029
}
4905
5030
}
5031
+
5032
+ void emitter::emitIns_SIMD_R_R_S (instruction ins, regNumber reg, regNumber reg1, int varx, int offs, var_types simdtype)
5033
+ {
5034
+ if (UseVEXEncoding ())
5035
+ {
5036
+ emitIns_R_R_S (ins, emitTypeSize (simdtype), reg, reg1, varx, offs);
5037
+ }
5038
+ else
5039
+ {
5040
+ if (reg1 != reg)
5041
+ {
5042
+ emitIns_R_R (INS_movaps, emitTypeSize (simdtype), reg, reg1);
5043
+ }
5044
+ emitIns_R_S (ins, emitTypeSize (simdtype), reg, varx, offs);
5045
+ }
5046
+ }
4906
5047
#endif
4907
5048
4908
5049
/* ****************************************************************************
@@ -6918,6 +7059,11 @@ void emitter::emitDispIns(
6918
7059
emitDispAddrMode (id);
6919
7060
break ;
6920
7061
7062
+ case IF_RWR_RRD_ARD:
7063
+ printf (" %s, %s, %s" , emitRegName (id->idReg1 (), attr), emitRegName (id->idReg2 (), attr), sstr);
7064
+ emitDispAddrMode (id);
7065
+ break ;
7066
+
6921
7067
case IF_ARD_RRD:
6922
7068
case IF_AWR_RRD:
6923
7069
case IF_ARW_RRD:
@@ -7061,6 +7207,12 @@ void emitter::emitDispIns(
7061
7207
7062
7208
break ;
7063
7209
7210
+ case IF_RWR_RRD_SRD:
7211
+ printf (" %s, %s, %s" , emitRegName (id->idReg1 (), attr), emitRegName (id->idReg2 (), attr), sstr);
7212
+ emitDispFrameRef (id->idAddr ()->iiaLclVar .lvaVarNum (), id->idAddr ()->iiaLclVar .lvaOffset (),
7213
+ id->idDebugOnlyInfo ()->idVarRefOffs , asmfm);
7214
+ break ;
7215
+
7064
7216
case IF_RRD_RRD:
7065
7217
case IF_RWR_RRD:
7066
7218
case IF_RRW_RRD:
@@ -7189,6 +7341,12 @@ void emitter::emitDispIns(
7189
7341
emitDispClsVar (id->idAddr ()->iiaFieldHnd , offs, ID_INFO_DSP_RELOC);
7190
7342
break ;
7191
7343
7344
+ case IF_RWR_RRD_MRD:
7345
+ printf (" %s, %s, %s" , emitRegName (id->idReg1 (), attr), emitRegName (id->idReg2 (), attr), sstr);
7346
+ offs = emitGetInsDsp (id);
7347
+ emitDispClsVar (id->idAddr ()->iiaFieldHnd , offs, ID_INFO_DSP_RELOC);
7348
+ break ;
7349
+
7192
7350
case IF_RWR_MRD_OFF:
7193
7351
7194
7352
printf (" %s, %s" , emitRegName (id->idReg1 (), attr), " offset" );
@@ -7635,12 +7793,17 @@ BYTE* emitter::emitOutputAM(BYTE* dst, instrDesc* id, code_t code, CnsVal* addc)
7635
7793
// Therefore, add VEX prefix is one is not already present.
7636
7794
code = AddVexPrefixIfNeededAndNotPresent (ins, code, size);
7637
7795
7638
- // For this format, moves do not support a third operand, so we only need to handle the binary ops.
7639
7796
if (IsDstDstSrcAVXInstruction (ins))
7640
7797
{
7641
- // Encode source operand reg in 'vvvv' bits in 1's complement form
7642
- // The order of operands are reversed, therefore use reg2 as the source.
7643
- code = insEncodeReg3456 (ins, id->idReg1 (), size, code);
7798
+ regNumber src1 = id->idReg2 ();
7799
+
7800
+ if (id->idInsFmt () != IF_RWR_RRD_ARD)
7801
+ {
7802
+ src1 = id->idReg1 ();
7803
+ }
7804
+
7805
+ // encode source operand reg in 'vvvv' bits in 1's compliement form
7806
+ code = insEncodeReg3456 (ins, src1, size, code);
7644
7807
}
7645
7808
7646
7809
// Emit the REX prefix if required
@@ -10988,6 +11151,7 @@ size_t emitter::emitOutputInstr(insGroup* ig, instrDesc* id, BYTE** dp)
10988
11151
case IF_RRD_ARD:
10989
11152
case IF_RWR_ARD:
10990
11153
case IF_RRW_ARD:
11154
+ case IF_RWR_RRD_ARD:
10991
11155
code = insCodeRM (ins);
10992
11156
code = AddVexPrefixIfNeeded (ins, code, size);
10993
11157
regcode = (insEncodeReg345 (ins, id->idReg1 (), size, &code) << 8 );
@@ -11082,6 +11246,7 @@ size_t emitter::emitOutputInstr(insGroup* ig, instrDesc* id, BYTE** dp)
11082
11246
case IF_RRD_SRD:
11083
11247
case IF_RWR_SRD:
11084
11248
case IF_RRW_SRD:
11249
+ case IF_RWR_RRD_SRD:
11085
11250
code = insCodeRM (ins);
11086
11251
11087
11252
// 4-byte AVX instructions are special cased inside emitOutputSV
@@ -11094,16 +11259,17 @@ size_t emitter::emitOutputInstr(insGroup* ig, instrDesc* id, BYTE** dp)
11094
11259
{
11095
11260
code = AddVexPrefixIfNeeded (ins, code, size);
11096
11261
11097
- // In case of AVX instructions that take 3 operands, encode reg1 as first source.
11098
- // Note that reg1 is both a source and a destination.
11099
- //
11100
- // TODO-XArch-CQ: Eventually we need to support 3 operand instruction formats. For
11101
- // now we use the single source as source1 and source2.
11102
- // For this format, moves do not support a third operand, so we only need to handle the binary ops.
11103
11262
if (IsDstDstSrcAVXInstruction (ins))
11104
11263
{
11264
+ regNumber src1 = id->idReg2 ();
11265
+
11266
+ if (id->idInsFmt () != IF_RWR_RRD_SRD)
11267
+ {
11268
+ src1 = id->idReg1 ();
11269
+ }
11270
+
11105
11271
// encode source operand reg in 'vvvv' bits in 1's compliement form
11106
- code = insEncodeReg3456 (ins, id-> idReg1 () , size, code);
11272
+ code = insEncodeReg3456 (ins, src1 , size, code);
11107
11273
}
11108
11274
11109
11275
regcode = (insEncodeReg345 (ins, id->idReg1 (), size, &code) << 8 );
@@ -11165,6 +11331,7 @@ size_t emitter::emitOutputInstr(insGroup* ig, instrDesc* id, BYTE** dp)
11165
11331
case IF_RRD_MRD:
11166
11332
case IF_RWR_MRD:
11167
11333
case IF_RRW_MRD:
11334
+ case IF_RWR_RRD_MRD:
11168
11335
code = insCodeRM (ins);
11169
11336
// Special case 4-byte AVX instructions
11170
11337
if (Is4ByteAVXInstruction (ins))
@@ -11175,16 +11342,17 @@ size_t emitter::emitOutputInstr(insGroup* ig, instrDesc* id, BYTE** dp)
11175
11342
{
11176
11343
code = AddVexPrefixIfNeeded (ins, code, size);
11177
11344
11178
- // In case of AVX instructions that take 3 operands, encode reg1 as first source.
11179
- // Note that reg1 is both a source and a destination.
11180
- //
11181
- // TODO-XArch-CQ: Eventually we need to support 3 operand instruction formats. For
11182
- // now we use the single source as source1 and source2.
11183
- // For this format, moves do not support a third operand, so we only need to handle the binary ops.
11184
11345
if (IsDstDstSrcAVXInstruction (ins))
11185
11346
{
11347
+ regNumber src1 = id->idReg2 ();
11348
+
11349
+ if (id->idInsFmt () != IF_RWR_RRD_MRD)
11350
+ {
11351
+ src1 = id->idReg1 ();
11352
+ }
11353
+
11186
11354
// encode source operand reg in 'vvvv' bits in 1's compliement form
11187
- code = insEncodeReg3456 (ins, id-> idReg1 () , size, code);
11355
+ code = insEncodeReg3456 (ins, src1 , size, code);
11188
11356
}
11189
11357
11190
11358
regcode = (insEncodeReg345 (ins, id->idReg1 (), size, &code) << 8 );
0 commit comments