@@ -1343,6 +1343,25 @@ void emitter::emitInsSanityCheck(instrDesc* id)
1343
1343
assert(isVectorRegister(id->idReg4())); // mmmmm
1344
1344
break;
1345
1345
1346
+ case IF_SVE_GQ_3A: // ................ ...gggnnnnnddddd -- SVE floating-point convert precision odd elements
1347
+ switch (id->idIns())
1348
+ {
1349
+ case INS_sve_fcvtnt:
1350
+ case INS_sve_fcvtlt:
1351
+ assert(insOptsConvertFloatStepwise(id->idInsOpt()));
1352
+ FALLTHROUGH;
1353
+ case INS_sve_fcvtxnt:
1354
+ case INS_sve_bfcvtnt:
1355
+ assert(isVectorRegister(id->idReg1())); // ddddd
1356
+ assert(isLowPredicateRegister(id->idReg2())); // ggg
1357
+ assert(isVectorRegister(id->idReg3())); // nnnnn
1358
+ break;
1359
+ default:
1360
+ assert(!"unreachable");
1361
+ break;
1362
+ }
1363
+ break;
1364
+
1346
1365
case IF_SVE_HT_4A: // ........xx.mmmmm ...gggnnnnn.DDDD -- SVE floating-point compare vectors
1347
1366
elemsize = id->idOpSize();
1348
1367
assert(isScalableVectorSize(elemsize));
@@ -6551,6 +6570,53 @@ emitter::code_t emitter::emitInsCodeSve(instruction ins, insFormat fmt)
6551
6570
return registerListSize;
6552
6571
}
6553
6572
6573
+ /*****************************************************************************
6574
+ *
6575
+ * Expands an option that has different size operands (INS_OPTS_*_TO_*) into
6576
+ * a pair of scalable options where the first describes the size of the
6577
+ * destination operand and the second describes the size of the source operand.
6578
+ */
6579
+
6580
+ /*static*/ void emitter::optExpandConversionPair(insOpts opt, insOpts& dst, insOpts& src)
6581
+ {
6582
+ dst = INS_OPTS_NONE;
6583
+ src = INS_OPTS_NONE;
6584
+
6585
+ switch (opt)
6586
+ {
6587
+ case INS_OPTS_H_TO_S:
6588
+ dst = INS_OPTS_SCALABLE_S;
6589
+ src = INS_OPTS_SCALABLE_H;
6590
+ break;
6591
+ case INS_OPTS_S_TO_H:
6592
+ dst = INS_OPTS_SCALABLE_H;
6593
+ src = INS_OPTS_SCALABLE_S;
6594
+ break;
6595
+ case INS_OPTS_S_TO_D:
6596
+ dst = INS_OPTS_SCALABLE_D;
6597
+ src = INS_OPTS_SCALABLE_S;
6598
+ break;
6599
+ case INS_OPTS_D_TO_S:
6600
+ dst = INS_OPTS_SCALABLE_S;
6601
+ src = INS_OPTS_SCALABLE_D;
6602
+ break;
6603
+ case INS_OPTS_H_TO_D:
6604
+ dst = INS_OPTS_SCALABLE_D;
6605
+ src = INS_OPTS_SCALABLE_H;
6606
+ break;
6607
+ case INS_OPTS_D_TO_H:
6608
+ dst = INS_OPTS_SCALABLE_H;
6609
+ src = INS_OPTS_SCALABLE_D;
6610
+ break;
6611
+ default:
6612
+ noway_assert(!"unreachable");
6613
+ break;
6614
+ }
6615
+
6616
+ assert(dst != INS_OPTS_NONE && src != INS_OPTS_NONE);
6617
+ return;
6618
+ }
6619
+
6554
6620
// For the given 'arrangement' returns the 'datasize' specified by the vector register arrangement
6555
6621
// asserts and returns EA_UNKNOWN if an invalid 'arrangement' value is passed
6556
6622
//
@@ -10890,6 +10956,18 @@ void emitter::emitIns_R_R_R(instruction ins,
10890
10956
fmt = IF_SVE_EU_3A;
10891
10957
break;
10892
10958
10959
+ case INS_sve_fcvtnt:
10960
+ case INS_sve_fcvtlt:
10961
+ assert(insOptsConvertFloatStepwise(opt));
10962
+ FALLTHROUGH;
10963
+ case INS_sve_fcvtxnt:
10964
+ case INS_sve_bfcvtnt:
10965
+ assert(isVectorRegister(reg1)); // ddddd
10966
+ assert(isLowPredicateRegister(reg2)); // ggg
10967
+ assert(isVectorRegister(reg3)); // nnnnn
10968
+ fmt = IF_SVE_GQ_3A;
10969
+ break;
10970
+
10893
10971
case INS_sve_faddp:
10894
10972
case INS_sve_fmaxnmp:
10895
10973
case INS_sve_fmaxp:
@@ -21284,6 +21362,24 @@ BYTE* emitter::emitOutput_InstrSve(BYTE* dst, instrDesc* id)
21284
21362
dst += emitOutput_Instr(dst, code);
21285
21363
break;
21286
21364
21365
+ case IF_SVE_GQ_3A: // ................ ...gggnnnnnddddd -- SVE floating-point convert precision odd elements
21366
+ code = emitInsCodeSve(ins, fmt);
21367
+
21368
+ if (ins == INS_sve_fcvtnt && id->idInsOpt() == INS_OPTS_D_TO_S)
21369
+ {
21370
+ code |= (1 << 22 | 1 << 17);
21371
+ }
21372
+ else if (ins == INS_sve_fcvtlt && id->idInsOpt() == INS_OPTS_S_TO_D)
21373
+ {
21374
+ code |= (1 << 22 | 1 << 17);
21375
+ }
21376
+
21377
+ code |= insEncodeReg_V_4_to_0(id->idReg1()); // ddddd
21378
+ code |= insEncodeReg_P_12_to_10(id->idReg2()); // ggg
21379
+ code |= insEncodeReg_V_9_to_5(id->idReg3()); // nnnnn
21380
+ dst += emitOutput_Instr(dst, code);
21381
+ break;
21382
+
21287
21383
// Scalable to general register.
21288
21384
case IF_SVE_CO_3A: // ........xx...... ...gggmmmmmddddd -- SVE conditionally extract element to general register
21289
21385
case IF_SVE_CS_3A: // ........xx...... ...gggnnnnnddddd -- SVE extract element to general register
@@ -25287,6 +25383,37 @@ void emitter::emitDispInsHelp(
25287
25383
break;
25288
25384
}
25289
25385
25386
+ // <Zd>.H, <Pg>/M, <Zn>.S
25387
+ // <Zd>.S, <Pg>/M, <Zn>.D
25388
+ // <Zd>.D, <Pg>/M, <Zn>.S
25389
+ // <Zd>.S, <Pg>/M, <Zn>.H
25390
+ case IF_SVE_GQ_3A: // ................ ...gggnnnnnddddd -- SVE floating-point convert precision odd elements
25391
+ {
25392
+ insOpts opt = id->idInsOpt();
25393
+
25394
+ switch (ins)
25395
+ {
25396
+ // These cases have only one combination of operands so the option may be omitted.
25397
+ case INS_sve_fcvtxnt:
25398
+ opt = INS_OPTS_D_TO_S;
25399
+ break;
25400
+ case INS_sve_bfcvtnt:
25401
+ opt = INS_OPTS_S_TO_H;
25402
+ break;
25403
+ default:
25404
+ break;
25405
+ }
25406
+
25407
+ insOpts dst = INS_OPTS_NONE;
25408
+ insOpts src = INS_OPTS_NONE;
25409
+ optExpandConversionPair(opt, dst, src);
25410
+
25411
+ emitDispSveReg(id->idReg1(), dst, true); // ddddd
25412
+ emitDispPredicateReg(id->idReg2(), insGetPredicateType(fmt), id->idInsOpt(), true); // ggg
25413
+ emitDispSveReg(id->idReg3(), src, false); // nnnnn
25414
+ break;
25415
+ }
25416
+
25290
25417
// { <Zt>.D }, <Pg>/Z, [<Xn|SP>{, #<imm>, MUL VL}]
25291
25418
// Some of these formats may allow changing the element size instead of using 'D' for all instructions.
25292
25419
case IF_SVE_IH_3A: // ............iiii ...gggnnnnnttttt -- SVE contiguous load (quadwords, scalar plus
@@ -28396,6 +28523,11 @@ emitter::insExecutionCharacteristics emitter::getInsExecutionCharacteristics(ins
28396
28523
result.insThroughput = PERFSCORE_THROUGHPUT_1C;
28397
28524
break;
28398
28525
28526
+ case IF_SVE_GQ_3A: // ................ ...gggnnnnnddddd -- SVE floating-point convert precision odd elements
28527
+ result.insThroughput = PERFSCORE_THROUGHPUT_1C;
28528
+ result.insLatency = PERFSCORE_LATENCY_3C;
28529
+ break;
28530
+
28399
28531
// Floating point arithmetic
28400
28532
// Floating point min/max pairwise
28401
28533
case IF_SVE_GR_3A: // ........xx...... ...gggmmmmmddddd -- SVE2 floating-point pairwise operations
0 commit comments