@@ -146,6 +146,7 @@ bool emitter::IsDstDstSrcAVXInstruction(instruction ins)
146
146
case INS_pminub:
147
147
case INS_pminud:
148
148
case INS_pminuw:
149
+ case INS_pmuldq:
149
150
case INS_pmulld:
150
151
case INS_pmullw:
151
152
case INS_pmuludq:
@@ -4227,6 +4228,45 @@ void emitter::emitIns_R_R_S_I(
4227
4228
emitCurIGsize += sz;
4228
4229
}
4229
4230
4231
+ #ifdef DEBUG
4232
+ static bool isAvxBlendv (instruction ins)
4233
+ {
4234
+ return ins == INS_vblendvps || ins == INS_vblendvpd || ins == INS_vpblendvb;
4235
+ }
4236
+
4237
+ static bool isSse41Blendv (instruction ins)
4238
+ {
4239
+ return ins == INS_blendvps || ins == INS_blendvpd || ins == INS_pblendvb;
4240
+ }
4241
+ #endif
4242
+
4243
+ void emitter::emitIns_R_R_R_R (
4244
+ instruction ins, emitAttr attr, regNumber targetReg, regNumber reg1, regNumber reg2, regNumber reg3)
4245
+ {
4246
+ assert (isAvxBlendv (ins));
4247
+ assert (UseVEXEncoding ());
4248
+ // Currently vex prefix only use three bytes mode.
4249
+ // size = vex + opcode + ModR/M + 1-byte-cns(Reg) = 3 + 1 + 1 + 1 = 6
4250
+ // TODO-XArch-CQ: We should create function which can calculate all kinds of AVX instructions size in future
4251
+ UNATIVE_OFFSET sz = 6 ;
4252
+
4253
+ // AVX/AVX2 supports 4-reg format for vblendvps/vblendvpd/vpblendvb,
4254
+ // which encodes the fourth register into imm8[7:4]
4255
+ int ival = (reg3 - XMMBASE) << 4 ; // convert reg3 to ival
4256
+
4257
+ instrDesc* id = emitNewInstrCns (attr, ival);
4258
+ id->idIns (ins);
4259
+ id->idInsFmt (IF_RWR_RRD_RRD_RRD);
4260
+ id->idReg1 (targetReg);
4261
+ id->idReg2 (reg1);
4262
+ id->idReg3 (reg2);
4263
+ id->idReg4 (reg3);
4264
+
4265
+ id->idCodeSize (sz);
4266
+ dispIns (id);
4267
+ emitCurIGsize += sz;
4268
+ }
4269
+
4230
4270
/* ****************************************************************************
4231
4271
*
4232
4272
* Add an instruction with a register + static member operands.
@@ -5166,158 +5206,191 @@ void emitter::emitIns_AX_R(instruction ins, emitAttr attr, regNumber ireg, regNu
5166
5206
}
5167
5207
5168
5208
#if FEATURE_HW_INTRINSICS
5169
- void emitter::emitIns_SIMD_R_R (instruction ins, regNumber reg, regNumber reg1, var_types simdtype )
5209
+ void emitter::emitIns_SIMD_R_R_A (instruction ins, emitAttr attr, regNumber reg, regNumber reg1, GenTreeIndir* indir )
5170
5210
{
5171
- emitIns_R_R (ins, emitTypeSize (simdtype), reg, reg1);
5211
+ if (UseVEXEncoding ())
5212
+ {
5213
+ emitIns_R_R_A (ins, attr, reg, reg1, indir, IF_RWR_RRD_ARD);
5214
+ }
5215
+ else
5216
+ {
5217
+ if (reg1 != reg)
5218
+ {
5219
+ emitIns_R_R (INS_movaps, attr, reg, reg1);
5220
+ }
5221
+ emitIns_R_A (ins, attr, reg, indir, IF_RRW_ARD);
5222
+ }
5172
5223
}
5173
5224
5174
- void emitter::emitIns_SIMD_R_R_A (
5175
- instruction ins, regNumber reg, regNumber reg1, GenTreeIndir* indir, var_types simdtype)
5225
+ void emitter::emitIns_SIMD_R_R_AR (instruction ins, emitAttr attr, regNumber reg, regNumber reg1, regNumber base)
5176
5226
{
5177
5227
if (UseVEXEncoding ())
5178
5228
{
5179
- emitIns_R_R_A (ins, emitTypeSize (simdtype) , reg, reg1, indir, IF_RWR_RRD_ARD );
5229
+ emitIns_R_R_AR (ins, attr , reg, reg1, base, 0 );
5180
5230
}
5181
5231
else
5182
5232
{
5183
5233
if (reg1 != reg)
5184
5234
{
5185
- emitIns_R_R (INS_movaps, emitTypeSize (simdtype) , reg, reg1);
5235
+ emitIns_R_R (INS_movaps, attr , reg, reg1);
5186
5236
}
5187
- emitIns_R_A (ins, emitTypeSize (simdtype) , reg, indir, IF_RRW_ARD );
5237
+ emitIns_R_AR (ins, attr , reg, base, 0 );
5188
5238
}
5189
5239
}
5190
5240
5191
- void emitter::emitIns_SIMD_R_R_AR (instruction ins, regNumber reg, regNumber reg1, regNumber base, var_types simdtype)
5241
+ void emitter::emitIns_SIMD_R_R_C (
5242
+ instruction ins, emitAttr attr, regNumber reg, regNumber reg1, CORINFO_FIELD_HANDLE fldHnd, int offs)
5192
5243
{
5193
5244
if (UseVEXEncoding ())
5194
5245
{
5195
- emitIns_R_R_AR (ins, emitTypeSize (simdtype) , reg, reg1, base, 0 );
5246
+ emitIns_R_R_C (ins, attr , reg, reg1, fldHnd, offs );
5196
5247
}
5197
5248
else
5198
5249
{
5199
5250
if (reg1 != reg)
5200
5251
{
5201
- emitIns_R_R (INS_movaps, emitTypeSize (simdtype) , reg, reg1);
5252
+ emitIns_R_R (INS_movaps, attr , reg, reg1);
5202
5253
}
5203
- emitIns_R_AR (ins, emitTypeSize (simdtype) , reg, base, 0 );
5254
+ emitIns_R_C (ins, attr , reg, fldHnd, offs );
5204
5255
}
5205
5256
}
5206
5257
5207
- void emitter::emitIns_SIMD_R_R_C (
5208
- instruction ins, regNumber reg, regNumber reg1, CORINFO_FIELD_HANDLE fldHnd, int offs, var_types simdtype)
5258
+ void emitter::emitIns_SIMD_R_R_R (instruction ins, emitAttr attr, regNumber reg, regNumber reg1, regNumber reg2)
5209
5259
{
5210
5260
if (UseVEXEncoding ())
5211
5261
{
5212
- emitIns_R_R_C (ins, emitTypeSize (simdtype) , reg, reg1, fldHnd, offs );
5262
+ emitIns_R_R_R (ins, attr , reg, reg1, reg2 );
5213
5263
}
5214
5264
else
5215
5265
{
5216
5266
if (reg1 != reg)
5217
5267
{
5218
- emitIns_R_R (INS_movaps, emitTypeSize (simdtype) , reg, reg1);
5268
+ emitIns_R_R (INS_movaps, attr , reg, reg1);
5219
5269
}
5220
- emitIns_R_C (ins, emitTypeSize (simdtype) , reg, fldHnd, offs );
5270
+ emitIns_R_R (ins, attr , reg, reg2 );
5221
5271
}
5222
5272
}
5223
5273
5224
- void emitter::emitIns_SIMD_R_R_R (instruction ins, regNumber reg, regNumber reg1, regNumber reg2, var_types simdtype)
5274
+ void emitter::emitIns_SIMD_R_R_R_R (
5275
+ instruction ins, emitAttr attr, regNumber reg, regNumber reg1, regNumber reg2, regNumber reg3)
5225
5276
{
5277
+ assert (isAvxBlendv (ins) || isSse41Blendv (ins));
5226
5278
if (UseVEXEncoding ())
5227
5279
{
5228
- emitIns_R_R_R (ins, emitTypeSize (simdtype), reg, reg1, reg2);
5280
+ // convert SSE encoding of SSE4.1 instructions to VEX encoding
5281
+ switch (ins)
5282
+ {
5283
+ case INS_blendvps:
5284
+ ins = INS_vblendvps;
5285
+ break ;
5286
+ case INS_blendvpd:
5287
+ ins = INS_vblendvpd;
5288
+ break ;
5289
+ case INS_pblendvb:
5290
+ ins = INS_vpblendvb;
5291
+ break ;
5292
+ default :
5293
+ break ;
5294
+ }
5295
+ emitIns_R_R_R_R (ins, attr, reg, reg1, reg2, reg3);
5229
5296
}
5230
5297
else
5231
5298
{
5299
+ assert (isSse41Blendv (ins));
5300
+ // SSE4.1 blendv* hardcode the mask vector (op3) in XMM0
5301
+ if (reg3 != REG_XMM0)
5302
+ {
5303
+ emitIns_R_R (INS_movaps, attr, REG_XMM0, reg3);
5304
+ }
5232
5305
if (reg1 != reg)
5233
5306
{
5234
- emitIns_R_R (INS_movaps, emitTypeSize (simdtype) , reg, reg1);
5307
+ emitIns_R_R (INS_movaps, attr , reg, reg1);
5235
5308
}
5236
- emitIns_R_R (ins, emitTypeSize (simdtype) , reg, reg2);
5309
+ emitIns_R_R (ins, attr , reg, reg2);
5237
5310
}
5238
5311
}
5239
5312
5240
- void emitter::emitIns_SIMD_R_R_S (instruction ins, regNumber reg, regNumber reg1, int varx, int offs, var_types simdtype )
5313
+ void emitter::emitIns_SIMD_R_R_S (instruction ins, emitAttr attr, regNumber reg, regNumber reg1, int varx, int offs)
5241
5314
{
5242
5315
if (UseVEXEncoding ())
5243
5316
{
5244
- emitIns_R_R_S (ins, emitTypeSize (simdtype) , reg, reg1, varx, offs);
5317
+ emitIns_R_R_S (ins, attr , reg, reg1, varx, offs);
5245
5318
}
5246
5319
else
5247
5320
{
5248
5321
if (reg1 != reg)
5249
5322
{
5250
- emitIns_R_R (INS_movaps, emitTypeSize (simdtype) , reg, reg1);
5323
+ emitIns_R_R (INS_movaps, attr , reg, reg1);
5251
5324
}
5252
- emitIns_R_S (ins, emitTypeSize (simdtype) , reg, varx, offs);
5325
+ emitIns_R_S (ins, attr , reg, varx, offs);
5253
5326
}
5254
5327
}
5255
5328
5256
5329
void emitter::emitIns_SIMD_R_R_A_I (
5257
- instruction ins, regNumber reg, regNumber reg1, GenTreeIndir* indir, int ival, var_types simdtype )
5330
+ instruction ins, emitAttr attr, regNumber reg, regNumber reg1, GenTreeIndir* indir, int ival)
5258
5331
{
5259
5332
if (UseVEXEncoding ())
5260
5333
{
5261
- emitIns_R_R_A_I (ins, emitTypeSize (simdtype) , reg, reg1, indir, ival, IF_RWR_RRD_ARD_CNS);
5334
+ emitIns_R_R_A_I (ins, attr , reg, reg1, indir, ival, IF_RWR_RRD_ARD_CNS);
5262
5335
}
5263
5336
else
5264
5337
{
5265
5338
if (reg1 != reg)
5266
5339
{
5267
- emitIns_R_R (INS_movaps, emitTypeSize (simdtype) , reg, reg1);
5340
+ emitIns_R_R (INS_movaps, attr , reg, reg1);
5268
5341
}
5269
- emitIns_R_A_I (ins, emitTypeSize (simdtype) , reg, indir, ival);
5342
+ emitIns_R_A_I (ins, attr , reg, indir, ival);
5270
5343
}
5271
5344
}
5272
5345
5273
5346
void emitter::emitIns_SIMD_R_R_C_I (
5274
- instruction ins, regNumber reg, regNumber reg1, CORINFO_FIELD_HANDLE fldHnd, int offs, int ival, var_types simdtype )
5347
+ instruction ins, emitAttr attr, regNumber reg, regNumber reg1, CORINFO_FIELD_HANDLE fldHnd, int offs, int ival)
5275
5348
{
5276
5349
if (UseVEXEncoding ())
5277
5350
{
5278
- emitIns_R_R_C_I (ins, emitTypeSize (simdtype) , reg, reg1, fldHnd, offs, ival);
5351
+ emitIns_R_R_C_I (ins, attr , reg, reg1, fldHnd, offs, ival);
5279
5352
}
5280
5353
else
5281
5354
{
5282
5355
if (reg1 != reg)
5283
5356
{
5284
- emitIns_R_R (INS_movaps, emitTypeSize (simdtype) , reg, reg1);
5357
+ emitIns_R_R (INS_movaps, attr , reg, reg1);
5285
5358
}
5286
- emitIns_R_C_I (ins, emitTypeSize (simdtype) , reg, fldHnd, offs, ival);
5359
+ emitIns_R_C_I (ins, attr , reg, fldHnd, offs, ival);
5287
5360
}
5288
5361
}
5289
5362
5290
5363
void emitter::emitIns_SIMD_R_R_R_I (
5291
- instruction ins, regNumber reg, regNumber reg1, regNumber reg2, int ival, var_types simdtype )
5364
+ instruction ins, emitAttr attr, regNumber reg, regNumber reg1, regNumber reg2, int ival)
5292
5365
{
5293
5366
if (UseVEXEncoding ())
5294
5367
{
5295
- emitIns_R_R_R_I (ins, emitTypeSize (simdtype) , reg, reg1, reg2, ival);
5368
+ emitIns_R_R_R_I (ins, attr , reg, reg1, reg2, ival);
5296
5369
}
5297
5370
else
5298
5371
{
5299
5372
if (reg1 != reg)
5300
5373
{
5301
- emitIns_R_R (INS_movaps, emitTypeSize (simdtype) , reg, reg1);
5374
+ emitIns_R_R (INS_movaps, attr , reg, reg1);
5302
5375
}
5303
- emitIns_R_R_I (ins, emitTypeSize (simdtype) , reg, reg2, ival);
5376
+ emitIns_R_R_I (ins, attr , reg, reg2, ival);
5304
5377
}
5305
5378
}
5306
5379
5307
5380
void emitter::emitIns_SIMD_R_R_S_I (
5308
- instruction ins, regNumber reg, regNumber reg1, int varx, int offs, int ival, var_types simdtype )
5381
+ instruction ins, emitAttr attr, regNumber reg, regNumber reg1, int varx, int offs, int ival)
5309
5382
{
5310
5383
if (UseVEXEncoding ())
5311
5384
{
5312
- emitIns_R_R_S_I (ins, emitTypeSize (simdtype) , reg, reg1, varx, offs, ival);
5385
+ emitIns_R_R_S_I (ins, attr , reg, reg1, varx, offs, ival);
5313
5386
}
5314
5387
else
5315
5388
{
5316
5389
if (reg1 != reg)
5317
5390
{
5318
- emitIns_R_R (INS_movaps, emitTypeSize (simdtype) , reg, reg1);
5391
+ emitIns_R_R (INS_movaps, attr , reg, reg1);
5319
5392
}
5320
- emitIns_R_S_I (ins, emitTypeSize (simdtype) , reg, varx, offs, ival);
5393
+ emitIns_R_S_I (ins, attr , reg, varx, offs, ival);
5321
5394
}
5322
5395
}
5323
5396
#endif
@@ -7653,6 +7726,14 @@ void emitter::emitDispIns(
7653
7726
val = emitGetInsSC (id);
7654
7727
goto PRINT_CONSTANT;
7655
7728
break ;
7729
+ case IF_RWR_RRD_RRD_RRD:
7730
+ assert (IsAVXOnlyInstruction (ins));
7731
+ assert (UseVEXEncoding ());
7732
+ printf (" %s, " , emitRegName (id->idReg1 (), attr));
7733
+ printf (" %s, " , emitRegName (id->idReg2 (), attr));
7734
+ printf (" %s, " , emitRegName (id->idReg3 (), attr));
7735
+ printf (" %s" , emitRegName (id->idReg4 (), attr));
7736
+ break ;
7656
7737
case IF_RRW_RRW_CNS:
7657
7738
printf (" %s," , emitRegName (id->idReg1 (), attr));
7658
7739
printf (" %s" , emitRegName (id->idReg2 (), attr));
@@ -10304,7 +10385,7 @@ BYTE* emitter::emitOutputRRR(BYTE* dst, instrDesc* id)
10304
10385
10305
10386
instruction ins = id->idIns ();
10306
10387
assert (IsAVXInstruction (ins));
10307
- assert (IsThreeOperandAVXInstruction (ins));
10388
+ assert (IsThreeOperandAVXInstruction (ins) || isAvxBlendv (ins) );
10308
10389
regNumber targetReg = id->idReg1 ();
10309
10390
regNumber src1 = id->idReg2 ();
10310
10391
regNumber src2 = id->idReg3 ();
@@ -11570,6 +11651,7 @@ size_t emitter::emitOutputInstr(insGroup* ig, instrDesc* id, BYTE** dp)
11570
11651
sz = emitSizeOfInsDsc (id);
11571
11652
break ;
11572
11653
case IF_RWR_RRD_RRD_CNS:
11654
+ case IF_RWR_RRD_RRD_RRD:
11573
11655
dst = emitOutputRRR (dst, id);
11574
11656
sz = emitSizeOfInsDsc (id);
11575
11657
dst += emitOutputByte (dst, emitGetInsSC (id));
0 commit comments