@@ -2722,6 +2722,48 @@ void emitter::emitInsSanityCheck(instrDesc* id)
27222722 assert(isScalableVectorSize(elemsize));
27232723 break;
27242724
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+
27252767 default:
27262768 printf("unexpected format %s\n", emitIfName(id->idInsFmt()));
27272769 assert(!"Unexpected format");
@@ -10131,6 +10173,48 @@ void emitter::emitIns_R_R_I(instruction ins,
1013110173 fmt = IF_SVE_FU_2A;
1013210174 break;
1013310175
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+
1013410218 default:
1013510219 unreached();
1013610220 break;
@@ -19405,6 +19489,49 @@ void emitter::emitIns_Call(EmitCallType callType,
1940519489 return (encoding | (code_t)(imm << 16));
1940619490}
1940719491
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+
1940819535/*****************************************************************************
1940919536 *
1941019537 * 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,
2150821635 return (code_t)imm << 14;
2150921636}
2151021637
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+
2151121649/*****************************************************************************
2151221650 *
2151321651 * 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)
2543325571 dst += emitOutput_Instr(dst, code);
2543425572 break;
2543525573
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+
2543625592 default:
2543725593 assert(!"Unexpected format");
2543825594 break;
@@ -29489,6 +29645,23 @@ void emitter::emitDispInsHelp(
2948929645 emitDispImm(imm, false);
2949029646 break;
2949129647
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+
2949229665 default:
2949329666 printf("unexpected format %s", emitIfName(id->idInsFmt()));
2949429667 assert(!"unexpectedFormat");
@@ -33687,6 +33860,16 @@ emitter::insExecutionCharacteristics emitter::getInsExecutionCharacteristics(ins
3368733860 result.insLatency = PERFSCORE_LATENCY_4C;
3368833861 break;
3368933862
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+
3369033873 default:
3369133874 // all other instructions
3369233875 perfScoreUnhandledInstruction(id, &result);
0 commit comments