@@ -2722,6 +2722,48 @@ void emitter::emitInsSanityCheck(instrDesc* id)
2722
2722
assert(isScalableVectorSize(elemsize));
2723
2723
break;
2724
2724
2725
+ case IF_SVE_BX_2A: // ...........ixxxx ......nnnnnddddd -- sve_int_perm_dupq_i
2726
+ imm = emitGetInsSC(id);
2727
+ elemsize = id->idOpSize();
2728
+ assert(insOptsScalableStandard(id->idInsOpt()));
2729
+ assert(isVectorRegister(id->idReg1()));
2730
+ assert(isVectorRegister(id->idReg2()));
2731
+ assert(isScalableVectorSize(elemsize));
2732
+ #ifdef DEBUG
2733
+ switch (id->idInsOpt())
2734
+ {
2735
+ case INS_OPTS_SCALABLE_B:
2736
+ assert(isValidUimm4(imm));
2737
+ break;
2738
+
2739
+ case INS_OPTS_SCALABLE_H:
2740
+ assert(isValidUimm3(imm));
2741
+ break;
2742
+
2743
+ case INS_OPTS_SCALABLE_S:
2744
+ assert(isValidUimm2(imm));
2745
+ break;
2746
+
2747
+ case INS_OPTS_SCALABLE_D:
2748
+ assert(isValidImm1(imm));
2749
+ break;
2750
+
2751
+ default:
2752
+ break;
2753
+ }
2754
+ #endif // DEBUG
2755
+ break;
2756
+
2757
+ case IF_SVE_BY_2A: // ............iiii ......mmmmmddddd -- sve_int_perm_extq
2758
+ imm = emitGetInsSC(id);
2759
+ elemsize = id->idOpSize();
2760
+ assert(id->idInsOpt() == INS_OPTS_SCALABLE_B);
2761
+ assert(isVectorRegister(id->idReg1()));
2762
+ assert(isVectorRegister(id->idReg2()));
2763
+ assert(isScalableVectorSize(elemsize));
2764
+ assert(isValidUimm4(imm));
2765
+ break;
2766
+
2725
2767
default:
2726
2768
printf("unexpected format %s\n", emitIfName(id->idInsFmt()));
2727
2769
assert(!"Unexpected format");
@@ -10131,6 +10173,48 @@ void emitter::emitIns_R_R_I(instruction ins,
10131
10173
fmt = IF_SVE_FU_2A;
10132
10174
break;
10133
10175
10176
+ case INS_sve_dupq:
10177
+ assert(insOptsScalableStandard(opt));
10178
+ assert(insScalableOptsNone(sopt));
10179
+ assert(isVectorRegister(reg1));
10180
+ assert(isVectorRegister(reg2));
10181
+ assert(isScalableVectorSize(size));
10182
+ #ifdef DEBUG
10183
+ switch (opt)
10184
+ {
10185
+ case INS_OPTS_SCALABLE_B:
10186
+ assert(isValidUimm4(imm));
10187
+ break;
10188
+
10189
+ case INS_OPTS_SCALABLE_H:
10190
+ assert(isValidUimm3(imm));
10191
+ break;
10192
+
10193
+ case INS_OPTS_SCALABLE_S:
10194
+ assert(isValidUimm2(imm));
10195
+ break;
10196
+
10197
+ case INS_OPTS_SCALABLE_D:
10198
+ assert(isValidImm1(imm));
10199
+ break;
10200
+
10201
+ default:
10202
+ break;
10203
+ }
10204
+ #endif // DEBUG
10205
+ fmt = IF_SVE_BX_2A;
10206
+ break;
10207
+
10208
+ case INS_sve_extq:
10209
+ assert(opt == INS_OPTS_SCALABLE_B);
10210
+ assert(insScalableOptsNone(sopt));
10211
+ assert(isVectorRegister(reg1));
10212
+ assert(isVectorRegister(reg2));
10213
+ assert(isScalableVectorSize(size));
10214
+ assert(isValidUimm4(imm));
10215
+ fmt = IF_SVE_BY_2A;
10216
+ break;
10217
+
10134
10218
default:
10135
10219
unreached();
10136
10220
break;
@@ -19405,6 +19489,49 @@ void emitter::emitIns_Call(EmitCallType callType,
19405
19489
return (encoding | (code_t)(imm << 16));
19406
19490
}
19407
19491
19492
+ /*****************************************************************************
19493
+ *
19494
+ * Returns the encoding for the field 'i1:tsz' at bit locations '20:19-16'.
19495
+ */
19496
+
19497
+ /*static*/ emitter::code_t emitter::insEncodeSveElemsizeWithImmediate_i1_tsz(const insOpts opt, ssize_t imm)
19498
+ {
19499
+ code_t encoding = 0;
19500
+
19501
+ switch (opt)
19502
+ {
19503
+ case INS_OPTS_SCALABLE_B:
19504
+ assert(isValidUimm4(imm));
19505
+ encoding |= (1 << 16); // bit 16
19506
+ encoding |= (imm << 17); // bits 20-17
19507
+ break;
19508
+
19509
+ case INS_OPTS_SCALABLE_H:
19510
+ assert(isValidUimm3(imm));
19511
+ encoding |= (1 << 17); // bit 17
19512
+ encoding |= (imm << 18); // bits 20-18
19513
+ break;
19514
+
19515
+ case INS_OPTS_SCALABLE_S:
19516
+ assert(isValidUimm2(imm));
19517
+ encoding |= (1 << 18); // bit 18
19518
+ encoding |= (imm << 19); // bits 20-19
19519
+ break;
19520
+
19521
+ case INS_OPTS_SCALABLE_D:
19522
+ assert(isValidImm1(imm));
19523
+ encoding |= (1 << 19); // bit 19
19524
+ encoding |= (imm << 20); // bit 20
19525
+ break;
19526
+
19527
+ default:
19528
+ assert(!"Invalid size for vector register");
19529
+ break;
19530
+ }
19531
+
19532
+ return encoding;
19533
+ }
19534
+
19408
19535
/*****************************************************************************
19409
19536
*
19410
19537
* Returns the encoding to select the elemsize for an Arm64 SVE vector instruction plus an immediate.
@@ -21508,6 +21635,17 @@ void emitter::emitIns_Call(EmitCallType callType,
21508
21635
return (code_t)imm << 14;
21509
21636
}
21510
21637
21638
+ /*****************************************************************************
21639
+ *
21640
+ * Returns the encoding for the immediate value as 4-bits at bit locations '19-16'.
21641
+ */
21642
+
21643
+ /*static*/ emitter::code_t emitter::insEncodeUimm4_19_to_16(ssize_t imm)
21644
+ {
21645
+ assert(isValidUimm4(imm));
21646
+ return (code_t)imm << 16;
21647
+ }
21648
+
21511
21649
/*****************************************************************************
21512
21650
*
21513
21651
* Returns the encoding for the immediate value as 4-bits starting from 1, at bit locations '19-16'.
@@ -25433,6 +25571,24 @@ BYTE* emitter::emitOutput_InstrSve(BYTE* dst, instrDesc* id)
25433
25571
dst += emitOutput_Instr(dst, code);
25434
25572
break;
25435
25573
25574
+ case IF_SVE_BX_2A: // ...........ixxxx ......nnnnnddddd -- sve_int_perm_dupq_i
25575
+ imm = emitGetInsSC(id);
25576
+ code = emitInsCodeSve(ins, fmt);
25577
+ code |= insEncodeReg_V_4_to_0(id->idReg1()); // ddddd
25578
+ code |= insEncodeReg_V_9_to_5(id->idReg2()); // nnnnn
25579
+ code |= insEncodeSveElemsizeWithImmediate_i1_tsz(id->idInsOpt(), imm); // ixxxx
25580
+ dst += emitOutput_Instr(dst, code);
25581
+ break;
25582
+
25583
+ case IF_SVE_BY_2A: // ............iiii ......mmmmmddddd -- sve_int_perm_extq
25584
+ imm = emitGetInsSC(id);
25585
+ code = emitInsCodeSve(ins, fmt);
25586
+ code |= insEncodeReg_V_4_to_0(id->idReg1()); // ddddd
25587
+ code |= insEncodeReg_V_9_to_5(id->idReg2()); // mmmmm
25588
+ code |= insEncodeUimm4_19_to_16(imm); // iiii
25589
+ dst += emitOutput_Instr(dst, code);
25590
+ break;
25591
+
25436
25592
default:
25437
25593
assert(!"Unexpected format");
25438
25594
break;
@@ -29489,6 +29645,23 @@ void emitter::emitDispInsHelp(
29489
29645
emitDispImm(imm, false);
29490
29646
break;
29491
29647
29648
+ // <Zd>.<T>, <Zn>.<T>[<imm>]
29649
+ case IF_SVE_BX_2A: // ...........ixxxx ......nnnnnddddd -- sve_int_perm_dupq_i
29650
+ imm = emitGetInsSC(id);
29651
+ emitDispSveReg(id->idReg1(), id->idInsOpt(), true);
29652
+ emitDispSveReg(id->idReg2(), id->idInsOpt(), false);
29653
+ emitDispElementIndex(imm, false);
29654
+ break;
29655
+
29656
+ // <Zdn>.B, <Zdn>.B, <Zm>.B, #<imm>
29657
+ case IF_SVE_BY_2A: // ............iiii ......mmmmmddddd -- sve_int_perm_extq
29658
+ imm = emitGetInsSC(id);
29659
+ emitDispSveReg(id->idReg1(), id->idInsOpt(), true);
29660
+ emitDispSveReg(id->idReg1(), id->idInsOpt(), true);
29661
+ emitDispSveReg(id->idReg2(), id->idInsOpt(), true);
29662
+ emitDispImm(imm, false);
29663
+ break;
29664
+
29492
29665
default:
29493
29666
printf("unexpected format %s", emitIfName(id->idInsFmt()));
29494
29667
assert(!"unexpectedFormat");
@@ -33687,6 +33860,16 @@ emitter::insExecutionCharacteristics emitter::getInsExecutionCharacteristics(ins
33687
33860
result.insLatency = PERFSCORE_LATENCY_4C;
33688
33861
break;
33689
33862
33863
+ case IF_SVE_BX_2A: // ...........ixxxx ......nnnnnddddd -- sve_int_perm_dupq_i
33864
+ result.insThroughput = PERFSCORE_THROUGHPUT_1C; // need to fix
33865
+ result.insLatency = PERFSCORE_LATENCY_1C; // need to fix
33866
+ break;
33867
+
33868
+ case IF_SVE_BY_2A: // ............iiii ......mmmmmddddd -- sve_int_perm_extq
33869
+ result.insThroughput = PERFSCORE_THROUGHPUT_1C; // need to fix
33870
+ result.insLatency = PERFSCORE_LATENCY_1C; // need to fix
33871
+ break;
33872
+
33690
33873
default:
33691
33874
// all other instructions
33692
33875
perfScoreUnhandledInstruction(id, &result);
0 commit comments