diff --git a/src/coreclr/jit/codegenarm64test.cpp b/src/coreclr/jit/codegenarm64test.cpp index d79b971840019..2d59d3e461541 100644 --- a/src/coreclr/jit/codegenarm64test.cpp +++ b/src/coreclr/jit/codegenarm64test.cpp @@ -4622,14 +4622,14 @@ void CodeGen::genArm64EmitterUnitTestsSve() INS_OPTS_SCALABLE_S); // MOVPRFX ., /, . theEmitter->emitIns_R_R_R(INS_sve_movprfx, EA_SCALABLE, REG_V15, REG_P3, REG_V2, INS_OPTS_SCALABLE_D); // MOVPRFX ., /, . - theEmitter->emitIns_R_R_R(INS_sve_movprfx, EA_SCALABLE, REG_V16, REG_P4, REG_V3, - INS_OPTS_SCALABLE_B_WITH_PREDICATE_MERGE); // MOVPRFX ., /, . - theEmitter->emitIns_R_R_R(INS_sve_movprfx, EA_SCALABLE, REG_V17, REG_P5, REG_V12, - INS_OPTS_SCALABLE_H_WITH_PREDICATE_MERGE); // MOVPRFX ., /, . - theEmitter->emitIns_R_R_R(INS_sve_movprfx, EA_SCALABLE, REG_V0, REG_P6, REG_V13, - INS_OPTS_SCALABLE_S_WITH_PREDICATE_MERGE); // MOVPRFX ., /, . - theEmitter->emitIns_R_R_R(INS_sve_movprfx, EA_SCALABLE, REG_V31, REG_P7, REG_V22, - INS_OPTS_SCALABLE_D_WITH_PREDICATE_MERGE); // MOVPRFX ., /, . + theEmitter->emitIns_R_R_R(INS_sve_movprfx, EA_SCALABLE, REG_V16, REG_P4, REG_V3, INS_OPTS_SCALABLE_B, + INS_SCALABLE_OPTS_PREDICATE_MERGE); // MOVPRFX ., /, . + theEmitter->emitIns_R_R_R(INS_sve_movprfx, EA_SCALABLE, REG_V17, REG_P5, REG_V12, INS_OPTS_SCALABLE_H, + INS_SCALABLE_OPTS_PREDICATE_MERGE); // MOVPRFX ., /, . + theEmitter->emitIns_R_R_R(INS_sve_movprfx, EA_SCALABLE, REG_V0, REG_P6, REG_V13, INS_OPTS_SCALABLE_S, + INS_SCALABLE_OPTS_PREDICATE_MERGE); // MOVPRFX ., /, . + theEmitter->emitIns_R_R_R(INS_sve_movprfx, EA_SCALABLE, REG_V31, REG_P7, REG_V22, INS_OPTS_SCALABLE_D, + INS_SCALABLE_OPTS_PREDICATE_MERGE); // MOVPRFX ., /, . // IF_SVE_AM_2A : right shifts theEmitter->emitIns_R_R_I(INS_sve_asr, EA_SCALABLE, REG_V0, REG_P0, 1, @@ -4718,12 +4718,12 @@ void CodeGen::genArm64EmitterUnitTestsSve() INS_OPTS_SCALABLE_S); // LSRR ., /M, ., . // IF_SVE_AO_3A - theEmitter->emitIns_R_R_R(INS_sve_asr, EA_SCALABLE, REG_V4, REG_P3, REG_V24, - INS_OPTS_SCALABLE_WIDE_B); // ASR ., /M, ., .D - theEmitter->emitIns_R_R_R(INS_sve_lsl, EA_SCALABLE, REG_V19, REG_P7, REG_V3, - INS_OPTS_SCALABLE_WIDE_H); // LSL ., /M, ., .D - theEmitter->emitIns_R_R_R(INS_sve_lsr, EA_SCALABLE, REG_V0, REG_P0, REG_V0, - INS_OPTS_SCALABLE_WIDE_S); // LSR ., /M, ., .D + theEmitter->emitIns_R_R_R(INS_sve_asr, EA_SCALABLE, REG_V4, REG_P3, REG_V24, INS_OPTS_SCALABLE_B, + INS_SCALABLE_OPTS_WIDE); // ASR ., /M, ., .D + theEmitter->emitIns_R_R_R(INS_sve_lsl, EA_SCALABLE, REG_V19, REG_P7, REG_V3, INS_OPTS_SCALABLE_H, + INS_SCALABLE_OPTS_WIDE); // LSL ., /M, ., .D + theEmitter->emitIns_R_R_R(INS_sve_lsr, EA_SCALABLE, REG_V0, REG_P0, REG_V0, INS_OPTS_SCALABLE_S, + INS_SCALABLE_OPTS_WIDE); // LSR ., /M, ., .D // IF_SVE_CM_3A theEmitter->emitIns_R_R_R(INS_sve_clasta, EA_SCALABLE, REG_V31, REG_P7, REG_V31, @@ -4732,23 +4732,23 @@ void CodeGen::genArm64EmitterUnitTestsSve() INS_OPTS_SCALABLE_D); // CLASTB ., , ., . // IF_SVE_CN_3A - theEmitter->emitIns_R_R_R(INS_sve_clasta, EA_2BYTE, REG_V12, REG_P1, REG_V15, - INS_OPTS_SCALABLE_H_WITH_SIMD_SCALAR); // CLASTA , , , . - theEmitter->emitIns_R_R_R(INS_sve_clastb, EA_4BYTE, REG_V13, REG_P2, REG_V16, - INS_OPTS_SCALABLE_S_WITH_SIMD_SCALAR); // CLASTB , , , . - theEmitter->emitIns_R_R_R(INS_sve_clastb, EA_8BYTE, REG_V14, REG_P0, REG_V17, - INS_OPTS_SCALABLE_D_WITH_SIMD_SCALAR); // CLASTB , , , . + theEmitter->emitIns_R_R_R(INS_sve_clasta, EA_2BYTE, REG_V12, REG_P1, REG_V15, INS_OPTS_SCALABLE_H, + INS_SCALABLE_OPTS_WITH_SIMD_SCALAR); // CLASTA , , , . + theEmitter->emitIns_R_R_R(INS_sve_clastb, EA_4BYTE, REG_V13, REG_P2, REG_V16, INS_OPTS_SCALABLE_S, + INS_SCALABLE_OPTS_WITH_SIMD_SCALAR); // CLASTB , , , . + theEmitter->emitIns_R_R_R(INS_sve_clastb, EA_8BYTE, REG_V14, REG_P0, REG_V17, INS_OPTS_SCALABLE_D, + INS_SCALABLE_OPTS_WITH_SIMD_SCALAR); // CLASTB , , , . // IF_SVE_CO_3A // Note: EA_4BYTE used for B and H (destination register is W) theEmitter->emitIns_R_R_R(INS_sve_clasta, EA_4BYTE, REG_R0, REG_P0, REG_V0, - INS_OPTS_SCALABLE_B_WITH_SCALAR); // CLASTA , , , . + INS_OPTS_SCALABLE_B); // CLASTA , , , . theEmitter->emitIns_R_R_R(INS_sve_clasta, EA_4BYTE, REG_R1, REG_P2, REG_V3, - INS_OPTS_SCALABLE_H_WITH_SCALAR); // CLASTA , , , . + INS_OPTS_SCALABLE_H); // CLASTA , , , . theEmitter->emitIns_R_R_R(INS_sve_clastb, EA_4BYTE, REG_R23, REG_P5, REG_V12, - INS_OPTS_SCALABLE_S_WITH_SCALAR); // CLASTB , , , . + INS_OPTS_SCALABLE_S); // CLASTB , , , . theEmitter->emitIns_R_R_R(INS_sve_clastb, EA_8BYTE, REG_R3, REG_P6, REG_V9, - INS_OPTS_SCALABLE_D_WITH_SCALAR); // CLASTB , , , . + INS_OPTS_SCALABLE_D); // CLASTB , , , . // IF_SVE_CX_4A theEmitter->emitIns_R_R_R_R(INS_sve_cmpeq, EA_SCALABLE, REG_P15, REG_P0, REG_V0, REG_V10, @@ -4860,11 +4860,11 @@ void CodeGen::genArm64EmitterUnitTestsSve() // IF_SVE_HJ_3A theEmitter->emitIns_R_R_R(INS_sve_fadda, EA_2BYTE, REG_V21, REG_P6, REG_V14, - INS_OPTS_SCALABLE_H_WITH_SIMD_SCALAR); // FADDA , , , . + INS_OPTS_SCALABLE_H); // FADDA , , , . theEmitter->emitIns_R_R_R(INS_sve_fadda, EA_4BYTE, REG_V22, REG_P5, REG_V13, - INS_OPTS_SCALABLE_S_WITH_SIMD_SCALAR); // FADDA , , , . + INS_OPTS_SCALABLE_S); // FADDA , , , . theEmitter->emitIns_R_R_R(INS_sve_fadda, EA_8BYTE, REG_V23, REG_P4, REG_V12, - INS_OPTS_SCALABLE_D_WITH_SIMD_SCALAR); // FADDA , , , . + INS_OPTS_SCALABLE_D); // FADDA , , , . // IF_SVE_HL_3A theEmitter->emitIns_R_R_R(INS_sve_fabd, EA_SCALABLE, REG_V24, REG_P3, REG_V11, @@ -4902,59 +4902,59 @@ void CodeGen::genArm64EmitterUnitTestsSve() // IF_SVE_AF_3A theEmitter->emitIns_R_R_R(INS_sve_andv, EA_1BYTE, REG_V0, REG_P0, REG_V0, - INS_OPTS_SCALABLE_B_WITH_SIMD_SCALAR); // ANDV , , . + INS_OPTS_SCALABLE_B); // ANDV , , . theEmitter->emitIns_R_R_R(INS_sve_eorv, EA_2BYTE, REG_V1, REG_P1, REG_V1, - INS_OPTS_SCALABLE_H_WITH_SIMD_SCALAR); // EORV , , . + INS_OPTS_SCALABLE_H); // EORV , , . theEmitter->emitIns_R_R_R(INS_sve_orv, EA_4BYTE, REG_V2, REG_P2, REG_V2, - INS_OPTS_SCALABLE_S_WITH_SIMD_SCALAR); // ORV , , . + INS_OPTS_SCALABLE_S); // ORV , , . theEmitter->emitIns_R_R_R(INS_sve_orv, EA_8BYTE, REG_V3, REG_P3, REG_V3, - INS_OPTS_SCALABLE_D_WITH_SIMD_SCALAR); // ORV , , . + INS_OPTS_SCALABLE_D); // ORV , , . // IF_SVE_AG_3A #ifdef ALL_ARM64_EMITTER_UNIT_TESTS_SVE_UNSUPPORTED - theEmitter->emitIns_R_R_R(INS_sve_andqv, EA_8BYTE, REG_V4, REG_P4, REG_V4, INS_OPTS_SCALABLE_B_WITH_SIMD_VECTOR); + theEmitter->emitIns_R_R_R(INS_sve_andqv, EA_8BYTE, REG_V4, REG_P4, REG_V4, INS_OPTS_SCALABLE_B); // ANDQV ., , . - theEmitter->emitIns_R_R_R(INS_sve_eorqv, EA_8BYTE, REG_V5, REG_P5, REG_V5, INS_OPTS_SCALABLE_H_WITH_SIMD_VECTOR); + theEmitter->emitIns_R_R_R(INS_sve_eorqv, EA_8BYTE, REG_V5, REG_P5, REG_V5, INS_OPTS_SCALABLE_H); // EORQV ., , . - theEmitter->emitIns_R_R_R(INS_sve_orqv, EA_8BYTE, REG_V6, REG_P6, REG_V6, INS_OPTS_SCALABLE_S_WITH_SIMD_VECTOR); + theEmitter->emitIns_R_R_R(INS_sve_orqv, EA_8BYTE, REG_V6, REG_P6, REG_V6, INS_OPTS_SCALABLE_S); // ORQV ., , . - theEmitter->emitIns_R_R_R(INS_sve_orqv, EA_8BYTE, REG_V7, REG_P7, REG_V7, INS_OPTS_SCALABLE_D_WITH_SIMD_VECTOR); + theEmitter->emitIns_R_R_R(INS_sve_orqv, EA_8BYTE, REG_V7, REG_P7, REG_V7, INS_OPTS_SCALABLE_D); // ORQV ., , . #endif // ALL_ARM64_EMITTER_UNIT_TESTS_SVE_UNSUPPORTED // IF_SVE_AI_3A theEmitter->emitIns_R_R_R(INS_sve_saddv, EA_1BYTE, REG_V1, REG_P4, REG_V2, - INS_OPTS_SCALABLE_B_WITH_SIMD_SCALAR); // SADDV
, , . + INS_OPTS_SCALABLE_B); // SADDV
, , . theEmitter->emitIns_R_R_R(INS_sve_saddv, EA_2BYTE, REG_V2, REG_P5, REG_V3, - INS_OPTS_SCALABLE_H_WITH_SIMD_SCALAR); // SADDV
, , . + INS_OPTS_SCALABLE_H); // SADDV
, , . theEmitter->emitIns_R_R_R(INS_sve_uaddv, EA_4BYTE, REG_V3, REG_P6, REG_V4, - INS_OPTS_SCALABLE_S_WITH_SIMD_SCALAR); // UADDV
, , . + INS_OPTS_SCALABLE_S); // UADDV
, , . // IF_SVE_AJ_3A #ifdef ALL_ARM64_EMITTER_UNIT_TESTS_SVE_UNSUPPORTED - theEmitter->emitIns_R_R_R(INS_sve_addqv, EA_8BYTE, REG_V21, REG_V7, REG_P22, INS_OPTS_SCALABLE_B_WITH_SIMD_VECTOR); + theEmitter->emitIns_R_R_R(INS_sve_addqv, EA_8BYTE, REG_V21, REG_P7, REG_V22, INS_OPTS_SCALABLE_B); // ADDQV ., , . #endif // ALL_ARM64_EMITTER_UNIT_TESTS_SVE_UNSUPPORTED // IF_SVE_AK_3A theEmitter->emitIns_R_R_R(INS_sve_smaxv, EA_8BYTE, REG_V15, REG_P7, REG_V4, - INS_OPTS_SCALABLE_D_WITH_SIMD_SCALAR); // SMAXV , , . + INS_OPTS_SCALABLE_D); // SMAXV , , . theEmitter->emitIns_R_R_R(INS_sve_sminv, EA_4BYTE, REG_V16, REG_P6, REG_V14, - INS_OPTS_SCALABLE_S_WITH_SIMD_SCALAR); // SMINV , , . + INS_OPTS_SCALABLE_S); // SMINV , , . theEmitter->emitIns_R_R_R(INS_sve_umaxv, EA_2BYTE, REG_V17, REG_P5, REG_V24, - INS_OPTS_SCALABLE_H_WITH_SIMD_SCALAR); // UMAXV , , . + INS_OPTS_SCALABLE_H); // UMAXV , , . theEmitter->emitIns_R_R_R(INS_sve_uminv, EA_1BYTE, REG_V18, REG_P4, REG_V31, - INS_OPTS_SCALABLE_B_WITH_SIMD_SCALAR); // UMINV , , . + INS_OPTS_SCALABLE_B); // UMINV , , . // IF_SVE_AL_3A #ifdef ALL_ARM64_EMITTER_UNIT_TESTS_SVE_UNSUPPORTED - theEmitter->emitIns_R_R_R(INS_sve_smaxqv, EA_8BYTE, REG_V0, REG_P5, REG_V25, INS_OPTS_SCALABLE_B_WITH_SIMD_VECTOR); + theEmitter->emitIns_R_R_R(INS_sve_smaxqv, EA_8BYTE, REG_V0, REG_P5, REG_V25, INS_OPTS_SCALABLE_B); // SMAXQV ., , . - theEmitter->emitIns_R_R_R(INS_sve_sminqv, EA_8BYTE, REG_V1, REG_P4, REG_V24, INS_OPTS_SCALABLE_H_WITH_SIMD_VECTOR); + theEmitter->emitIns_R_R_R(INS_sve_sminqv, EA_8BYTE, REG_V1, REG_P4, REG_V24, INS_OPTS_SCALABLE_H); // SMINQV ., , . - theEmitter->emitIns_R_R_R(INS_sve_umaxqv, EA_8BYTE, REG_V2, REG_P3, REG_V23, INS_OPTS_SCALABLE_S_WITH_SIMD_VECTOR); + theEmitter->emitIns_R_R_R(INS_sve_umaxqv, EA_8BYTE, REG_V2, REG_P3, REG_V23, INS_OPTS_SCALABLE_S); // UMAXQV ., , . - theEmitter->emitIns_R_R_R(INS_sve_uminqv, EA_8BYTE, REG_V3, REG_P2, REG_V22, INS_OPTS_SCALABLE_D_WITH_SIMD_VECTOR); + theEmitter->emitIns_R_R_R(INS_sve_uminqv, EA_8BYTE, REG_V3, REG_P2, REG_V22, INS_OPTS_SCALABLE_D); // UMINQV ., , . #endif // ALL_ARM64_EMITTER_UNIT_TESTS_SVE_UNSUPPORTED @@ -5023,46 +5023,46 @@ void CodeGen::genArm64EmitterUnitTestsSve() INS_OPTS_SCALABLE_D); // COMPACT ., , . // IF_SVE_CP_3A - theEmitter->emitIns_R_R_R(INS_sve_cpy, EA_1BYTE, REG_V14, REG_P1, REG_V11, - INS_OPTS_SCALABLE_B_WITH_SIMD_SCALAR); // CPY ., /M, - theEmitter->emitIns_R_R_R(INS_sve_cpy, EA_4BYTE, REG_V13, REG_P2, REG_V10, - INS_OPTS_SCALABLE_S_WITH_SIMD_SCALAR); // CPY ., /M, - theEmitter->emitIns_R_R_R(INS_sve_mov, EA_2BYTE, REG_V12, REG_P3, REG_V9, - INS_OPTS_SCALABLE_H_WITH_SIMD_SCALAR); // MOV ., /M, - theEmitter->emitIns_R_R_R(INS_sve_mov, EA_8BYTE, REG_V11, REG_P4, REG_V8, - INS_OPTS_SCALABLE_D_WITH_SIMD_SCALAR); // MOV ., /M, + theEmitter->emitIns_R_R_R(INS_sve_cpy, EA_1BYTE, REG_V14, REG_P1, REG_V11, INS_OPTS_SCALABLE_B, + INS_SCALABLE_OPTS_WITH_SIMD_SCALAR); // CPY ., /M, + theEmitter->emitIns_R_R_R(INS_sve_cpy, EA_4BYTE, REG_V13, REG_P2, REG_V10, INS_OPTS_SCALABLE_S, + INS_SCALABLE_OPTS_WITH_SIMD_SCALAR); // CPY ., /M, + theEmitter->emitIns_R_R_R(INS_sve_mov, EA_2BYTE, REG_V12, REG_P3, REG_V9, INS_OPTS_SCALABLE_H, + INS_SCALABLE_OPTS_WITH_SIMD_SCALAR); // MOV ., /M, + theEmitter->emitIns_R_R_R(INS_sve_mov, EA_8BYTE, REG_V11, REG_P4, REG_V8, INS_OPTS_SCALABLE_D, + INS_SCALABLE_OPTS_WITH_SIMD_SCALAR); // MOV ., /M, // IF_SVE_CQ_3A // Note: EA_4BYTE used for B and H (source register is W) theEmitter->emitIns_R_R_R(INS_sve_cpy, EA_8BYTE, REG_V10, REG_P5, REG_SP, - INS_OPTS_SCALABLE_D_WITH_SCALAR); // CPY ., /M, + INS_OPTS_SCALABLE_D); // CPY ., /M, theEmitter->emitIns_R_R_R(INS_sve_cpy, EA_4BYTE, REG_V9, REG_P6, REG_R30, - INS_OPTS_SCALABLE_H_WITH_SCALAR); // CPY ., /M, + INS_OPTS_SCALABLE_H); // CPY ., /M, theEmitter->emitIns_R_R_R(INS_sve_mov, EA_4BYTE, REG_V8, REG_P7, REG_R29, - INS_OPTS_SCALABLE_S_WITH_SCALAR); // MOV ., /M, + INS_OPTS_SCALABLE_S); // MOV ., /M, theEmitter->emitIns_R_R_R(INS_sve_mov, EA_4BYTE, REG_V7, REG_P0, REG_R28, - INS_OPTS_SCALABLE_B_WITH_SCALAR); // MOV ., /M, + INS_OPTS_SCALABLE_B); // MOV ., /M, // IF_SVE_CR_3A - theEmitter->emitIns_R_R_R(INS_sve_lasta, EA_1BYTE, REG_V6, REG_P1, REG_V27, - INS_OPTS_SCALABLE_B_WITH_SIMD_SCALAR); // LASTA , , . - theEmitter->emitIns_R_R_R(INS_sve_lasta, EA_2BYTE, REG_V5, REG_P2, REG_V26, - INS_OPTS_SCALABLE_H_WITH_SIMD_SCALAR); // LASTA , , . - theEmitter->emitIns_R_R_R(INS_sve_lastb, EA_4BYTE, REG_V4, REG_P3, REG_V25, - INS_OPTS_SCALABLE_S_WITH_SIMD_SCALAR); // LASTB , , . - theEmitter->emitIns_R_R_R(INS_sve_lastb, EA_8BYTE, REG_V3, REG_P4, REG_V24, - INS_OPTS_SCALABLE_D_WITH_SIMD_SCALAR); // LASTB , , . + theEmitter->emitIns_R_R_R(INS_sve_lasta, EA_1BYTE, REG_V6, REG_P1, REG_V27, INS_OPTS_SCALABLE_B, + INS_SCALABLE_OPTS_WITH_SIMD_SCALAR); // LASTA , , . + theEmitter->emitIns_R_R_R(INS_sve_lasta, EA_2BYTE, REG_V5, REG_P2, REG_V26, INS_OPTS_SCALABLE_H, + INS_SCALABLE_OPTS_WITH_SIMD_SCALAR); // LASTA , , . + theEmitter->emitIns_R_R_R(INS_sve_lastb, EA_4BYTE, REG_V4, REG_P3, REG_V25, INS_OPTS_SCALABLE_S, + INS_SCALABLE_OPTS_WITH_SIMD_SCALAR); // LASTB , , . + theEmitter->emitIns_R_R_R(INS_sve_lastb, EA_8BYTE, REG_V3, REG_P4, REG_V24, INS_OPTS_SCALABLE_D, + INS_SCALABLE_OPTS_WITH_SIMD_SCALAR); // LASTB , , . // IF_SVE_CS_3A // Note: EA_4BYTE used for B and H (source register is W) theEmitter->emitIns_R_R_R(INS_sve_lasta, EA_4BYTE, REG_R1, REG_P5, REG_V23, - INS_OPTS_SCALABLE_B_WITH_SCALAR); // LASTA , , . + INS_OPTS_SCALABLE_B); // LASTA , , . theEmitter->emitIns_R_R_R(INS_sve_lasta, EA_4BYTE, REG_R0, REG_P6, REG_V22, - INS_OPTS_SCALABLE_S_WITH_SCALAR); // LASTA , , . + INS_OPTS_SCALABLE_S); // LASTA , , . theEmitter->emitIns_R_R_R(INS_sve_lastb, EA_4BYTE, REG_R30, REG_P7, REG_V21, - INS_OPTS_SCALABLE_H_WITH_SCALAR); // LASTB , , . + INS_OPTS_SCALABLE_H); // LASTB , , . theEmitter->emitIns_R_R_R(INS_sve_lastb, EA_8BYTE, REG_R29, REG_P0, REG_V20, - INS_OPTS_SCALABLE_D_WITH_SCALAR); // LASTB , , . + INS_OPTS_SCALABLE_D); // LASTB , , . // IF_SVE_CU_3A theEmitter->emitIns_R_R_R(INS_sve_rbit, EA_SCALABLE, REG_V28, REG_P1, REG_V19, @@ -5130,23 +5130,15 @@ void CodeGen::genArm64EmitterUnitTestsSve() INS_OPTS_SCALABLE_H); // UQRSHRN .H, {.S-.S }, # // IF_SVE_DM_2A - theEmitter->emitIns_R_R(INS_sve_decp, EA_8BYTE, REG_R0, REG_P0, - INS_OPTS_SCALABLE_B_WITH_SCALAR); // DECP , . - theEmitter->emitIns_R_R(INS_sve_decp, EA_8BYTE, REG_R1, REG_P1, - INS_OPTS_SCALABLE_H_WITH_SCALAR); // DECP , . - theEmitter->emitIns_R_R(INS_sve_decp, EA_8BYTE, REG_R2, REG_P2, - INS_OPTS_SCALABLE_S_WITH_SCALAR); // DECP , . - theEmitter->emitIns_R_R(INS_sve_decp, EA_8BYTE, REG_R3, REG_P3, - INS_OPTS_SCALABLE_D_WITH_SCALAR); // DECP , . - - theEmitter->emitIns_R_R(INS_sve_incp, EA_8BYTE, REG_R4, REG_P4, - INS_OPTS_SCALABLE_B_WITH_SCALAR); // INCP , . - theEmitter->emitIns_R_R(INS_sve_incp, EA_8BYTE, REG_R5, REG_P5, - INS_OPTS_SCALABLE_H_WITH_SCALAR); // INCP , . - theEmitter->emitIns_R_R(INS_sve_incp, EA_8BYTE, REG_R6, REG_P6, - INS_OPTS_SCALABLE_S_WITH_SCALAR); // INCP , . - theEmitter->emitIns_R_R(INS_sve_incp, EA_8BYTE, REG_R7, REG_P7, - INS_OPTS_SCALABLE_D_WITH_SCALAR); // INCP , . + theEmitter->emitIns_R_R(INS_sve_decp, EA_8BYTE, REG_R0, REG_P0, INS_OPTS_SCALABLE_B); // DECP , . + theEmitter->emitIns_R_R(INS_sve_decp, EA_8BYTE, REG_R1, REG_P1, INS_OPTS_SCALABLE_H); // DECP , . + theEmitter->emitIns_R_R(INS_sve_decp, EA_8BYTE, REG_R2, REG_P2, INS_OPTS_SCALABLE_S); // DECP , . + theEmitter->emitIns_R_R(INS_sve_decp, EA_8BYTE, REG_R3, REG_P3, INS_OPTS_SCALABLE_D); // DECP , . + + theEmitter->emitIns_R_R(INS_sve_incp, EA_8BYTE, REG_R4, REG_P4, INS_OPTS_SCALABLE_B); // INCP , . + theEmitter->emitIns_R_R(INS_sve_incp, EA_8BYTE, REG_R5, REG_P5, INS_OPTS_SCALABLE_H); // INCP , . + theEmitter->emitIns_R_R(INS_sve_incp, EA_8BYTE, REG_R6, REG_P6, INS_OPTS_SCALABLE_S); // INCP , . + theEmitter->emitIns_R_R(INS_sve_incp, EA_8BYTE, REG_R7, REG_P7, INS_OPTS_SCALABLE_D); // INCP , . // IF_SVE_DN_2A // Note: B is reserved @@ -5160,76 +5152,52 @@ void CodeGen::genArm64EmitterUnitTestsSve() // IF_SVE_DO_2A theEmitter->emitIns_R_R(INS_sve_sqdecp, EA_4BYTE, REG_R0, REG_P0, - INS_OPTS_SCALABLE_B_WITH_SCALAR); // SQDECP , ., + INS_OPTS_SCALABLE_B); // SQDECP , ., theEmitter->emitIns_R_R(INS_sve_sqdecp, EA_4BYTE, REG_R1, REG_P1, - INS_OPTS_SCALABLE_H_WITH_SCALAR); // SQDECP , ., + INS_OPTS_SCALABLE_H); // SQDECP , ., theEmitter->emitIns_R_R(INS_sve_sqdecp, EA_4BYTE, REG_R2, REG_P2, - INS_OPTS_SCALABLE_S_WITH_SCALAR); // SQDECP , ., + INS_OPTS_SCALABLE_S); // SQDECP , ., theEmitter->emitIns_R_R(INS_sve_sqdecp, EA_4BYTE, REG_R3, REG_P3, - INS_OPTS_SCALABLE_D_WITH_SCALAR); // SQDECP , ., + INS_OPTS_SCALABLE_D); // SQDECP , ., - theEmitter->emitIns_R_R(INS_sve_sqdecp, EA_8BYTE, REG_R4, REG_P4, - INS_OPTS_SCALABLE_B_WITH_SCALAR); // SQDECP , . - theEmitter->emitIns_R_R(INS_sve_sqdecp, EA_8BYTE, REG_R5, REG_P5, - INS_OPTS_SCALABLE_H_WITH_SCALAR); // SQDECP , . - theEmitter->emitIns_R_R(INS_sve_sqdecp, EA_8BYTE, REG_R6, REG_P6, - INS_OPTS_SCALABLE_S_WITH_SCALAR); // SQDECP , . - theEmitter->emitIns_R_R(INS_sve_sqdecp, EA_8BYTE, REG_R7, REG_P7, - INS_OPTS_SCALABLE_D_WITH_SCALAR); // SQDECP , . + theEmitter->emitIns_R_R(INS_sve_sqdecp, EA_8BYTE, REG_R4, REG_P4, INS_OPTS_SCALABLE_B); // SQDECP , . + theEmitter->emitIns_R_R(INS_sve_sqdecp, EA_8BYTE, REG_R5, REG_P5, INS_OPTS_SCALABLE_H); // SQDECP , . + theEmitter->emitIns_R_R(INS_sve_sqdecp, EA_8BYTE, REG_R6, REG_P6, INS_OPTS_SCALABLE_S); // SQDECP , . + theEmitter->emitIns_R_R(INS_sve_sqdecp, EA_8BYTE, REG_R7, REG_P7, INS_OPTS_SCALABLE_D); // SQDECP , . theEmitter->emitIns_R_R(INS_sve_sqincp, EA_4BYTE, REG_R0, REG_P0, - INS_OPTS_SCALABLE_H_WITH_SCALAR); // SQINCP , ., + INS_OPTS_SCALABLE_H); // SQINCP , ., theEmitter->emitIns_R_R(INS_sve_sqincp, EA_4BYTE, REG_R1, REG_P1, - INS_OPTS_SCALABLE_S_WITH_SCALAR); // SQINCP , ., + INS_OPTS_SCALABLE_S); // SQINCP , ., theEmitter->emitIns_R_R(INS_sve_sqincp, EA_4BYTE, REG_R2, REG_P2, - INS_OPTS_SCALABLE_B_WITH_SCALAR); // SQINCP , ., + INS_OPTS_SCALABLE_B); // SQINCP , ., theEmitter->emitIns_R_R(INS_sve_sqincp, EA_4BYTE, REG_R3, REG_P3, - INS_OPTS_SCALABLE_D_WITH_SCALAR); // SQINCP , ., - - theEmitter->emitIns_R_R(INS_sve_sqincp, EA_8BYTE, REG_R4, REG_P4, - INS_OPTS_SCALABLE_B_WITH_SCALAR); // SQINCP , . - theEmitter->emitIns_R_R(INS_sve_sqincp, EA_8BYTE, REG_R5, REG_P5, - INS_OPTS_SCALABLE_H_WITH_SCALAR); // SQINCP , . - theEmitter->emitIns_R_R(INS_sve_sqincp, EA_8BYTE, REG_R6, REG_P6, - INS_OPTS_SCALABLE_S_WITH_SCALAR); // SQINCP , . - theEmitter->emitIns_R_R(INS_sve_sqincp, EA_8BYTE, REG_R7, REG_P7, - INS_OPTS_SCALABLE_D_WITH_SCALAR); // SQINCP , . - - theEmitter->emitIns_R_R(INS_sve_uqdecp, EA_4BYTE, REG_R0, REG_P0, - INS_OPTS_SCALABLE_B_WITH_SCALAR); // UQDECP , . - theEmitter->emitIns_R_R(INS_sve_uqdecp, EA_4BYTE, REG_R1, REG_P1, - INS_OPTS_SCALABLE_H_WITH_SCALAR); // UQDECP , . - theEmitter->emitIns_R_R(INS_sve_uqdecp, EA_4BYTE, REG_R2, REG_P2, - INS_OPTS_SCALABLE_S_WITH_SCALAR); // UQDECP , . - theEmitter->emitIns_R_R(INS_sve_uqdecp, EA_4BYTE, REG_R3, REG_P3, - INS_OPTS_SCALABLE_D_WITH_SCALAR); // UQDECP , . - - theEmitter->emitIns_R_R(INS_sve_uqdecp, EA_8BYTE, REG_R4, REG_P4, - INS_OPTS_SCALABLE_B_WITH_SCALAR); // UQDECP , . - theEmitter->emitIns_R_R(INS_sve_uqdecp, EA_8BYTE, REG_R5, REG_P5, - INS_OPTS_SCALABLE_H_WITH_SCALAR); // UQDECP , . - theEmitter->emitIns_R_R(INS_sve_uqdecp, EA_8BYTE, REG_R6, REG_P6, - INS_OPTS_SCALABLE_S_WITH_SCALAR); // UQDECP , . - theEmitter->emitIns_R_R(INS_sve_uqdecp, EA_8BYTE, REG_R7, REG_P7, - INS_OPTS_SCALABLE_D_WITH_SCALAR); // UQDECP , . - - theEmitter->emitIns_R_R(INS_sve_uqincp, EA_4BYTE, REG_R0, REG_P0, - INS_OPTS_SCALABLE_B_WITH_SCALAR); // UQINCP , . - theEmitter->emitIns_R_R(INS_sve_uqincp, EA_4BYTE, REG_R1, REG_P1, - INS_OPTS_SCALABLE_H_WITH_SCALAR); // UQINCP , . - theEmitter->emitIns_R_R(INS_sve_uqincp, EA_4BYTE, REG_R2, REG_P2, - INS_OPTS_SCALABLE_S_WITH_SCALAR); // UQINCP , . - theEmitter->emitIns_R_R(INS_sve_uqincp, EA_4BYTE, REG_R3, REG_P3, - INS_OPTS_SCALABLE_D_WITH_SCALAR); // UQINCP , . - - theEmitter->emitIns_R_R(INS_sve_uqincp, EA_8BYTE, REG_R4, REG_P4, - INS_OPTS_SCALABLE_B_WITH_SCALAR); // UQINCP , . - theEmitter->emitIns_R_R(INS_sve_uqincp, EA_8BYTE, REG_R5, REG_P5, - INS_OPTS_SCALABLE_H_WITH_SCALAR); // UQINCP , . - theEmitter->emitIns_R_R(INS_sve_uqincp, EA_8BYTE, REG_R6, REG_P6, - INS_OPTS_SCALABLE_S_WITH_SCALAR); // UQINCP , . - theEmitter->emitIns_R_R(INS_sve_uqincp, EA_8BYTE, REG_R7, REG_P7, - INS_OPTS_SCALABLE_D_WITH_SCALAR); // UQINCP , . + INS_OPTS_SCALABLE_D); // SQINCP , ., + + theEmitter->emitIns_R_R(INS_sve_sqincp, EA_8BYTE, REG_R4, REG_P4, INS_OPTS_SCALABLE_B); // SQINCP , . + theEmitter->emitIns_R_R(INS_sve_sqincp, EA_8BYTE, REG_R5, REG_P5, INS_OPTS_SCALABLE_H); // SQINCP , . + theEmitter->emitIns_R_R(INS_sve_sqincp, EA_8BYTE, REG_R6, REG_P6, INS_OPTS_SCALABLE_S); // SQINCP , . + theEmitter->emitIns_R_R(INS_sve_sqincp, EA_8BYTE, REG_R7, REG_P7, INS_OPTS_SCALABLE_D); // SQINCP , . + + theEmitter->emitIns_R_R(INS_sve_uqdecp, EA_4BYTE, REG_R0, REG_P0, INS_OPTS_SCALABLE_B); // UQDECP , . + theEmitter->emitIns_R_R(INS_sve_uqdecp, EA_4BYTE, REG_R1, REG_P1, INS_OPTS_SCALABLE_H); // UQDECP , . + theEmitter->emitIns_R_R(INS_sve_uqdecp, EA_4BYTE, REG_R2, REG_P2, INS_OPTS_SCALABLE_S); // UQDECP , . + theEmitter->emitIns_R_R(INS_sve_uqdecp, EA_4BYTE, REG_R3, REG_P3, INS_OPTS_SCALABLE_D); // UQDECP , . + + theEmitter->emitIns_R_R(INS_sve_uqdecp, EA_8BYTE, REG_R4, REG_P4, INS_OPTS_SCALABLE_B); // UQDECP , . + theEmitter->emitIns_R_R(INS_sve_uqdecp, EA_8BYTE, REG_R5, REG_P5, INS_OPTS_SCALABLE_H); // UQDECP , . + theEmitter->emitIns_R_R(INS_sve_uqdecp, EA_8BYTE, REG_R6, REG_P6, INS_OPTS_SCALABLE_S); // UQDECP , . + theEmitter->emitIns_R_R(INS_sve_uqdecp, EA_8BYTE, REG_R7, REG_P7, INS_OPTS_SCALABLE_D); // UQDECP , . + + theEmitter->emitIns_R_R(INS_sve_uqincp, EA_4BYTE, REG_R0, REG_P0, INS_OPTS_SCALABLE_B); // UQINCP , . + theEmitter->emitIns_R_R(INS_sve_uqincp, EA_4BYTE, REG_R1, REG_P1, INS_OPTS_SCALABLE_H); // UQINCP , . + theEmitter->emitIns_R_R(INS_sve_uqincp, EA_4BYTE, REG_R2, REG_P2, INS_OPTS_SCALABLE_S); // UQINCP , . + theEmitter->emitIns_R_R(INS_sve_uqincp, EA_4BYTE, REG_R3, REG_P3, INS_OPTS_SCALABLE_D); // UQINCP , . + + theEmitter->emitIns_R_R(INS_sve_uqincp, EA_8BYTE, REG_R4, REG_P4, INS_OPTS_SCALABLE_B); // UQINCP , . + theEmitter->emitIns_R_R(INS_sve_uqincp, EA_8BYTE, REG_R5, REG_P5, INS_OPTS_SCALABLE_H); // UQINCP , . + theEmitter->emitIns_R_R(INS_sve_uqincp, EA_8BYTE, REG_R6, REG_P6, INS_OPTS_SCALABLE_S); // UQINCP , . + theEmitter->emitIns_R_R(INS_sve_uqincp, EA_8BYTE, REG_R7, REG_P7, INS_OPTS_SCALABLE_D); // UQINCP , . // IF_SVE_DP_2A // NOTE: B is reserved @@ -5325,28 +5293,28 @@ void CodeGen::genArm64EmitterUnitTestsSve() // IF_SVE_GS_3A #ifdef ALL_ARM64_EMITTER_UNIT_TESTS_SVE_UNSUPPORTED theEmitter->emitIns_R_R_R(INS_sve_faddqv, EA_8BYTE, REG_V16, REG_P0, REG_V12, - INS_OPTS_SCALABLE_H_WITH_SIMD_VECTOR); // FADDQV ., , . + INS_OPTS_SCALABLE_H); // FADDQV ., , . theEmitter->emitIns_R_R_R(INS_sve_fmaxnmqv, EA_8BYTE, REG_V17, REG_P1, REG_V11, - INS_OPTS_SCALABLE_S_WITH_SIMD_VECTOR); // FMAXNMQV ., , . + INS_OPTS_SCALABLE_S); // FMAXNMQV ., , . theEmitter->emitIns_R_R_R(INS_sve_fmaxqv, EA_8BYTE, REG_V18, REG_P3, REG_V10, - INS_OPTS_SCALABLE_D_WITH_SIMD_VECTOR); // FMAXQV ., , . + INS_OPTS_SCALABLE_D); // FMAXQV ., , . theEmitter->emitIns_R_R_R(INS_sve_fminnmqv, EA_8BYTE, REG_V19, REG_P4, REG_V9, - INS_OPTS_SCALABLE_H_WITH_SIMD_VECTOR); // FMINNMQV ., , . + INS_OPTS_SCALABLE_H); // FMINNMQV ., , . theEmitter->emitIns_R_R_R(INS_sve_fminqv, EA_8BYTE, REG_V20, REG_P5, REG_V8, - INS_OPTS_SCALABLE_D_WITH_SIMD_VECTOR); // FMINQV ., , . -#endif // ALL_ARM64_EMITTER_UNIT_TESTS_SVE_UNSUPPORTED + INS_OPTS_SCALABLE_D); // FMINQV ., , . +#endif // ALL_ARM64_EMITTER_UNIT_TESTS_SVE_UNSUPPORTED // IF_SVE_HE_3A theEmitter->emitIns_R_R_R(INS_sve_faddv, EA_2BYTE, REG_V21, REG_P7, REG_V7, - INS_OPTS_SCALABLE_H_WITH_SIMD_SCALAR); // FADDV , , . + INS_OPTS_SCALABLE_H); // FADDV , , . theEmitter->emitIns_R_R_R(INS_sve_fmaxnmv, EA_2BYTE, REG_V22, REG_P6, REG_V6, - INS_OPTS_SCALABLE_H_WITH_SIMD_SCALAR); // FMAXNMV , , . + INS_OPTS_SCALABLE_H); // FMAXNMV , , . theEmitter->emitIns_R_R_R(INS_sve_fmaxv, EA_4BYTE, REG_V23, REG_P5, REG_V5, - INS_OPTS_SCALABLE_S_WITH_SIMD_SCALAR); // FMAXV , , . + INS_OPTS_SCALABLE_S); // FMAXV , , . theEmitter->emitIns_R_R_R(INS_sve_fminnmv, EA_8BYTE, REG_V24, REG_P4, REG_V4, - INS_OPTS_SCALABLE_D_WITH_SIMD_SCALAR); // FMINNMV , , . + INS_OPTS_SCALABLE_D); // FMINNMV , , . theEmitter->emitIns_R_R_R(INS_sve_fminv, EA_4BYTE, REG_V25, REG_P3, REG_V3, - INS_OPTS_SCALABLE_S_WITH_SIMD_SCALAR); // FMINV , , . + INS_OPTS_SCALABLE_S); // FMINV , , . // IF_SVE_HQ_3A theEmitter->emitIns_R_R_R(INS_sve_frinta, EA_SCALABLE, REG_V26, REG_P7, REG_V2, diff --git a/src/coreclr/jit/emit.h b/src/coreclr/jit/emit.h index 148339bae4fc5..e45e1c5da5505 100644 --- a/src/coreclr/jit/emit.h +++ b/src/coreclr/jit/emit.h @@ -978,7 +978,7 @@ class emitter #ifdef TARGET_ARM64 // For 64-bit architecture this 32-bit structure can pack with these unsigned bit fields emitLclVarAddr iiaLclVar; - unsigned _idReg3Scaled : 1; // Reg3 is scaled by idOpSize bits + unsigned _idRegBit : 1; // Reg3 is scaled by idOpSize bits GCtype _idGCref2 : 2; #endif regNumber _idReg3 : REGNUM_BITS; @@ -1402,12 +1402,22 @@ class emitter bool idReg3Scaled() const { assert(!idIsSmallDsc()); - return (idAddr()->_idReg3Scaled == 1); + return (idAddr()->_idRegBit == 1); } void idReg3Scaled(bool val) { assert(!idIsSmallDsc()); - idAddr()->_idReg3Scaled = val ? 1 : 0; + idAddr()->_idRegBit = val ? 1 : 0; + } + bool idPredicateReg2Merge() const + { + assert(!idIsSmallDsc()); + return (idAddr()->_idRegBit == 1); + } + void idPredicateReg2Merge(bool val) + { + assert(!idIsSmallDsc()); + idAddr()->_idRegBit = val ? 1 : 0; } #endif // TARGET_ARM64 diff --git a/src/coreclr/jit/emitarm64.cpp b/src/coreclr/jit/emitarm64.cpp index 67c3be9be944a..f0e6f1d27da34 100644 --- a/src/coreclr/jit/emitarm64.cpp +++ b/src/coreclr/jit/emitarm64.cpp @@ -956,10 +956,10 @@ void emitter::emitInsSanityCheck(instrDesc* id) case IF_SVE_EU_3A: // ........xx...... ...gggmmmmmddddd -- SVE2 saturating/rounding bitwise shift left // (predicated) elemsize = id->idOpSize(); - assert(insOptsScalableSimple(id->idInsOpt())); // xx - assert(isVectorRegister(id->idReg1())); // ddddd - assert(isLowPredicateRegister(id->idReg2())); // ggg - assert(isVectorRegister(id->idReg3())); // mmmmm + assert(insOptsScalableStandard(id->idInsOpt())); // xx + assert(isVectorRegister(id->idReg1())); // ddddd + assert(isLowPredicateRegister(id->idReg2())); // ggg + assert(isVectorRegister(id->idReg3())); // mmmmm assert(isScalableVectorSize(elemsize)); break; @@ -977,7 +977,7 @@ void emitter::emitInsSanityCheck(instrDesc* id) // Scalable, Merge or Zero predicate. case IF_SVE_AH_3A: // ........xx.....M ...gggnnnnnddddd -- SVE constructive prefix (predicated) elemsize = id->idOpSize(); - assert(insOptsScalableSimple(id->idInsOpt()) || insOptsScalableWithPredicateMerge(id->idInsOpt())); + assert(insOptsScalableStandard(id->idInsOpt())); assert(isVectorRegister(id->idReg1())); // nnnnn assert(isLowPredicateRegister(id->idReg2())); // ggg assert(isVectorRegister(id->idReg3())); // ddddd @@ -987,7 +987,7 @@ void emitter::emitInsSanityCheck(instrDesc* id) // Scalable, with shift immediate. case IF_SVE_AM_2A: // ........xx...... ...gggxxiiiddddd -- SVE bitwise shift by immediate (predicated) elemsize = id->idOpSize(); - assert(insOptsScalableSimple(id->idInsOpt())); + assert(insOptsScalableStandard(id->idInsOpt())); assert(isVectorRegister(id->idReg1())); // ddddd assert(isLowPredicateRegister(id->idReg2())); // ggg assert(isValidVectorShiftAmount(emitGetInsSC(id), optGetSveElemsize(id->idInsOpt()), true)); @@ -1012,10 +1012,10 @@ void emitter::emitInsSanityCheck(instrDesc* id) // (predicated) case IF_SVE_CR_3A: // ........xx...... ...gggnnnnnddddd -- SVE extract element to SIMD&FP scalar register elemsize = id->idOpSize(); - assert(insOptsScalableWithSimdScalar(id->idInsOpt())); // xx - assert(isVectorRegister(id->idReg1())); // ddddd - assert(isLowPredicateRegister(id->idReg2())); // ggg - assert(isVectorRegister(id->idReg3())); // mmmmm + assert(insOptsScalableStandard(id->idInsOpt())); // xx + assert(isVectorRegister(id->idReg1())); // ddddd + assert(isLowPredicateRegister(id->idReg2())); // ggg + assert(isVectorRegister(id->idReg3())); // mmmmm assert(isValidVectorElemsize(elemsize)); break; @@ -1023,10 +1023,10 @@ void emitter::emitInsSanityCheck(instrDesc* id) case IF_SVE_HE_3A: // ........xx...... ...gggnnnnnddddd -- SVE floating-point recursive reduction case IF_SVE_HJ_3A: // ........xx...... ...gggmmmmmddddd -- SVE floating-point serial reduction (predicated) elemsize = id->idOpSize(); - assert(insOptsScalableWithSimdFPScalar(id->idInsOpt())); // xx - assert(isVectorRegister(id->idReg1())); // ddddd - assert(isLowPredicateRegister(id->idReg2())); // ggg - assert(isVectorRegister(id->idReg3())); // mmmmm + assert(insOptsScalableFloat(id->idInsOpt())); // xx + assert(isVectorRegister(id->idReg1())); // ddddd + assert(isLowPredicateRegister(id->idReg2())); // ggg + assert(isVectorRegister(id->idReg3())); // mmmmm assert(isValidVectorElemsizeSveFloat(elemsize)); break; @@ -1034,10 +1034,10 @@ void emitter::emitInsSanityCheck(instrDesc* id) case IF_SVE_CO_3A: // ........xx...... ...gggmmmmmddddd -- SVE conditionally extract element to general register case IF_SVE_CS_3A: // ........xx...... ...gggnnnnnddddd -- SVE extract element to general register elemsize = id->idOpSize(); - assert(insOptsScalableWithScalar(id->idInsOpt())); // xx - assert(isGeneralRegister(id->idReg1())); // ddddd - assert(isLowPredicateRegister(id->idReg2())); // ggg - assert(isVectorRegister(id->idReg3())); // mmmmm + assert(insOptsScalableStandard(id->idInsOpt())); // xx + assert(isGeneralRegister(id->idReg1())); // ddddd + assert(isLowPredicateRegister(id->idReg2())); // ggg + assert(isVectorRegister(id->idReg3())); // mmmmm assert(isValidScalarDatasize(elemsize)); break; @@ -1047,9 +1047,9 @@ void emitter::emitInsSanityCheck(instrDesc* id) case IF_SVE_AS_4A: // ........xx.mmmmm ...gggaaaaaddddd -- SVE integer multiply-add writing multiplicand // (predicated) elemsize = id->idOpSize(); - assert(insOptsScalableSimple(id->idInsOpt())); // xx - assert(isVectorRegister(id->idReg1())); // ddddd - assert(isLowPredicateRegister(id->idReg2())); // ggg + assert(insOptsScalableStandard(id->idInsOpt())); // xx + assert(isVectorRegister(id->idReg1())); // ddddd + assert(isLowPredicateRegister(id->idReg2())); // ggg assert(isVectorRegister(id->idReg3())); assert(isVectorRegister(id->idReg4())); assert(isScalableVectorSize(elemsize)); @@ -1058,11 +1058,11 @@ void emitter::emitInsSanityCheck(instrDesc* id) // Scalable, 4 regs, to predicate register. case IF_SVE_CX_4A: // ........xx.mmmmm ...gggnnnnn.DDDD -- SVE integer compare vectors elemsize = id->idOpSize(); - assert(insOptsScalableSimple(id->idInsOpt())); // xx - assert(isPredicateRegister(id->idReg1())); // DDDD - assert(isLowPredicateRegister(id->idReg2())); // ggg - assert(isVectorRegister(id->idReg3())); // mmmmm - assert(isVectorRegister(id->idReg4())); // nnnnn + assert(insOptsScalableStandard(id->idInsOpt())); // xx + assert(isPredicateRegister(id->idReg1())); // DDDD + assert(isLowPredicateRegister(id->idReg2())); // ggg + assert(isVectorRegister(id->idReg3())); // mmmmm + assert(isVectorRegister(id->idReg4())); // nnnnn assert(isScalableVectorSize(elemsize)); break; @@ -1082,22 +1082,31 @@ void emitter::emitInsSanityCheck(instrDesc* id) case IF_SVE_AG_3A: // ........xx...... ...gggnnnnnddddd -- SVE bitwise logical reduction (quadwords) case IF_SVE_AJ_3A: // ........xx...... ...gggnnnnnddddd -- SVE integer add reduction (quadwords) case IF_SVE_AL_3A: // ........xx...... ...gggnnnnnddddd -- SVE integer min/max reduction (quadwords) + datasize = id->idOpSize(); + assert(insOptsScalableStandard(id->idInsOpt())); // xx + assert(isVectorRegister(id->idReg1())); // ddddd + assert(isLowPredicateRegister(id->idReg2())); // ggg + assert(isVectorRegister(id->idReg3())); // mmmmm + assert(datasize == EA_8BYTE); + break; + + // Scalable FP to Simd Vector. case IF_SVE_GS_3A: // ........xx...... ...gggnnnnnddddd -- SVE floating-point recursive reduction (quadwords) datasize = id->idOpSize(); - assert(insOptsScalableWithSimdVector(id->idInsOpt())); // xx - assert(isVectorRegister(id->idReg1())); // ddddd - assert(isLowPredicateRegister(id->idReg2())); // ggg - assert(isVectorRegister(id->idReg3())); // mmmmm + assert(insOptsScalableFloat(id->idInsOpt())); // xx + assert(isVectorRegister(id->idReg1())); // ddddd + assert(isLowPredicateRegister(id->idReg2())); // ggg + assert(isVectorRegister(id->idReg3())); // mmmmm assert(datasize == EA_8BYTE); break; // Scalable, widening to scalar SIMD. case IF_SVE_AI_3A: // ........xx...... ...gggnnnnnddddd -- SVE integer add reduction (predicated) elemsize = id->idOpSize(); - assert(insOptsScalableWideningToSimdScalar(id->idInsOpt())); // xx - assert(isVectorRegister(id->idReg1())); // ddddd - assert(isLowPredicateRegister(id->idReg2())); // ggg - assert(isVectorRegister(id->idReg3())); // mmmmm + assert(insOptsScalableWide(id->idInsOpt())); // xx + assert(isVectorRegister(id->idReg1())); // ddddd + assert(isLowPredicateRegister(id->idReg2())); // ggg + assert(isVectorRegister(id->idReg3())); // mmmmm assert(isValidVectorElemsizeWidening(elemsize)); break; @@ -1111,7 +1120,7 @@ void emitter::emitInsSanityCheck(instrDesc* id) break; default: - assert(insOptsScalableSimple(id->idInsOpt())); // xx + assert(insOptsScalableStandard(id->idInsOpt())); // xx break; } elemsize = id->idOpSize(); @@ -1129,7 +1138,7 @@ void emitter::emitInsSanityCheck(instrDesc* id) case INS_sve_abs: case INS_sve_neg: case INS_sve_rbit: - assert(insOptsScalableSimple(id->idInsOpt())); + assert(insOptsScalableStandard(id->idInsOpt())); break; case INS_sve_sxtb: @@ -1158,10 +1167,10 @@ void emitter::emitInsSanityCheck(instrDesc* id) // Scalable from general scalar (possibly SP) case IF_SVE_CQ_3A: // ........xx...... ...gggnnnnnddddd -- SVE copy general register to vector (predicated) elemsize = id->idOpSize(); - assert(insOptsScalableWithScalar(id->idInsOpt())); // xx - assert(isVectorRegister(id->idReg1())); // ddddd - assert(isLowPredicateRegister(id->idReg2())); // ggg - assert(isGeneralRegisterOrZR(id->idReg3())); // mmmmm + assert(insOptsScalableStandard(id->idInsOpt())); // xx + assert(isVectorRegister(id->idReg1())); // ddddd + assert(isLowPredicateRegister(id->idReg2())); // ggg + assert(isGeneralRegisterOrZR(id->idReg3())); // mmmmm assert(isValidScalarDatasize(elemsize)); break; @@ -1183,7 +1192,7 @@ void emitter::emitInsSanityCheck(instrDesc* id) { case INS_sve_sqabs: case INS_sve_sqneg: - assert(insOptsScalableSimple(id->idInsOpt())); + assert(insOptsScalableStandard(id->idInsOpt())); break; default: @@ -1208,9 +1217,9 @@ void emitter::emitInsSanityCheck(instrDesc* id) FALLTHROUGH; case IF_SVE_DM_2A: // ........xx...... .......MMMMddddd -- SVE inc/dec register by predicate count - assert(insOptsScalableWithScalar(id->idInsOpt())); // xx - assert(isGeneralRegister(id->idReg1())); // ddddd - assert(isPredicateRegister(id->idReg2())); // MMMM + assert(insOptsScalableStandard(id->idInsOpt())); // xx + assert(isGeneralRegister(id->idReg1())); // ddddd + assert(isPredicateRegister(id->idReg2())); // MMMM assert(isValidGeneralDatasize(id->idOpSize())); break; @@ -1238,7 +1247,7 @@ void emitter::emitInsSanityCheck(instrDesc* id) break; case IF_SVE_GD_2A: // .........x.xx... ......nnnnnddddd -- SVE2 saturating extract narrow - assert(insOptsScalableSimple(id->idInsOpt())); + assert(insOptsScalableStandard(id->idInsOpt())); assert(isVectorRegister(id->idReg1())); // nnnnn assert(isVectorRegister(id->idReg2())); // ddddd assert(optGetSveElemsize(id->idInsOpt()) != EA_8BYTE); @@ -1248,7 +1257,7 @@ void emitter::emitInsSanityCheck(instrDesc* id) case IF_SVE_GK_2A: // ................ ......mmmmmddddd -- SVE2 crypto destructive binary operations elemsize = id->idOpSize(); - assert(insOptsScalableSimple(id->idInsOpt())); + assert(insOptsScalableStandard(id->idInsOpt())); assert(isVectorRegister(id->idReg1())); // ddddd assert(isVectorRegister(id->idReg2())); // mmmmm #ifdef DEBUG @@ -1266,7 +1275,7 @@ void emitter::emitInsSanityCheck(instrDesc* id) case IF_SVE_GL_1A: // ................ ...........ddddd -- SVE2 crypto unary operations elemsize = id->idOpSize(); - assert(insOptsScalableSimple(id->idInsOpt())); + assert(insOptsScalableStandard(id->idInsOpt())); assert(isVectorRegister(id->idReg1())); // ddddd assert(isScalableVectorSize(elemsize)); break; @@ -5454,34 +5463,15 @@ emitter::code_t emitter::emitInsCodeSve(instruction ins, insFormat fmt) switch (arrangement) { case INS_OPTS_SCALABLE_B: - case INS_OPTS_SCALABLE_WIDE_B: - case INS_OPTS_SCALABLE_B_WITH_SIMD_SCALAR: - case INS_OPTS_SCALABLE_B_WITH_SIMD_VECTOR: - case INS_OPTS_SCALABLE_B_WITH_SCALAR: - case INS_OPTS_SCALABLE_B_WITH_PREDICATE_MERGE: return EA_1BYTE; case INS_OPTS_SCALABLE_H: - case INS_OPTS_SCALABLE_WIDE_H: - case INS_OPTS_SCALABLE_H_WITH_SIMD_SCALAR: - case INS_OPTS_SCALABLE_H_WITH_SIMD_VECTOR: - case INS_OPTS_SCALABLE_H_WITH_SCALAR: - case INS_OPTS_SCALABLE_H_WITH_PREDICATE_MERGE: return EA_2BYTE; case INS_OPTS_SCALABLE_S: - case INS_OPTS_SCALABLE_WIDE_S: - case INS_OPTS_SCALABLE_S_WITH_SIMD_SCALAR: - case INS_OPTS_SCALABLE_S_WITH_SIMD_VECTOR: - case INS_OPTS_SCALABLE_S_WITH_SCALAR: - case INS_OPTS_SCALABLE_S_WITH_PREDICATE_MERGE: return EA_4BYTE; case INS_OPTS_SCALABLE_D: - case INS_OPTS_SCALABLE_D_WITH_SIMD_SCALAR: - case INS_OPTS_SCALABLE_D_WITH_SIMD_VECTOR: - case INS_OPTS_SCALABLE_D_WITH_SCALAR: - case INS_OPTS_SCALABLE_D_WITH_PREDICATE_MERGE: return EA_8BYTE; case INS_OPTS_SCALABLE_Q: @@ -5533,6 +5523,28 @@ emitter::code_t emitter::emitInsCodeSve(instruction ins, insFormat fmt) } } +/*static*/ insOpts emitter::optSveToQuadwordElemsizeArrangement(insOpts arrangement) +{ + switch (arrangement) + { + case INS_OPTS_SCALABLE_B: + return INS_OPTS_16B; + + case INS_OPTS_SCALABLE_H: + return INS_OPTS_8H; + + case INS_OPTS_SCALABLE_S: + return INS_OPTS_4S; + + case INS_OPTS_SCALABLE_D: + return INS_OPTS_2D; + + default: + assert(!" invalid 'arrangement' value"); + return INS_OPTS_NONE; + } +} + /*static*/ emitAttr emitter::widenDatasize(emitAttr datasize) { if (datasize == EA_1BYTE) @@ -7027,7 +7039,7 @@ void emitter::emitIns_R_R( if (isGeneralRegister(reg1)) // ddddd { - assert(insOptsScalableWithScalar(opt)); // xx + assert(insOptsScalableStandard(opt)); // xx assert(size == EA_8BYTE); fmt = IF_SVE_DM_2A; } @@ -7048,7 +7060,7 @@ void emitter::emitIns_R_R( if (isGeneralRegister(reg1)) // ddddd { - assert(insOptsScalableWithScalar(opt)); // xx + assert(insOptsScalableStandard(opt)); // xx assert(isValidGeneralDatasize(size)); fmt = IF_SVE_DO_2A; } @@ -7076,7 +7088,7 @@ void emitter::emitIns_R_R( case INS_sve_uqxtnt: case INS_sve_sqxtunb: case INS_sve_sqxtunt: - assert(insOptsScalable(opt)); + assert(insOptsScalableStandard(opt)); assert(isVectorRegister(reg1)); assert(isVectorRegister(reg2)); assert(optGetSveElemsize(opt) != EA_8BYTE); @@ -7088,7 +7100,7 @@ void emitter::emitIns_R_R( case INS_sve_aese: case INS_sve_aesd: case INS_sve_sm4e: - assert(insOptsScalable(opt)); + assert(insOptsScalableStandard(opt)); assert(isVectorRegister(reg1)); assert(isVectorRegister(reg2)); #ifdef DEBUG @@ -7812,7 +7824,7 @@ void emitter::emitIns_R_R_I( case INS_sve_uqshl: case INS_sve_asrd: isRightShift = emitInsIsVectorRightShift(ins); - assert(insOptsScalableSimple(opt)); + assert(insOptsScalableStandard(opt)); assert(isVectorRegister(reg1)); // ddddd assert(isLowPredicateRegister(reg2)); // ggg assert(isValidVectorShiftAmount(imm, optGetSveElemsize(opt), isRightShift)); @@ -8033,12 +8045,18 @@ void emitter::emitIns_R_R_Imm(instruction ins, emitAttr attr, regNumber reg1, re * Add an instruction referencing three registers. */ -void emitter::emitIns_R_R_R( - instruction ins, emitAttr attr, regNumber reg1, regNumber reg2, regNumber reg3, insOpts opt) /* = INS_OPTS_NONE */ +void emitter::emitIns_R_R_R(instruction ins, + emitAttr attr, + regNumber reg1, + regNumber reg2, + regNumber reg3, + insOpts opt /* = INS_OPTS_NONE */, + insScalableOpts sopt /* = INS_SCALABLE_OPTS_NONE */) { emitAttr size = EA_SIZE(attr); emitAttr elemsize = EA_UNKNOWN; insFormat fmt = IF_NONE; + bool pmerge = false; /* Figure out the encoding format of the instruction */ switch (ins) @@ -8693,7 +8711,8 @@ void emitter::emitIns_R_R_R( assert(isVectorRegister(reg1)); assert(isLowPredicateRegister(reg2)); assert(isVectorRegister(reg3)); - assert(insOptsScalableSimple(opt)); + assert(insOptsScalableStandard(opt)); + assert(insScalableOptsNone(sopt)); fmt = IF_SVE_AA_3A; break; @@ -8703,7 +8722,8 @@ void emitter::emitIns_R_R_R( assert(isVectorRegister(reg1)); assert(isLowPredicateRegister(reg2)); assert(isVectorRegister(reg3)); - assert(insOptsScalableSimple(opt)); + assert(insOptsScalableStandard(opt)); + assert(insScalableOptsNone(sopt)); fmt = IF_SVE_AB_3A; break; @@ -8715,6 +8735,7 @@ void emitter::emitIns_R_R_R( assert(isLowPredicateRegister(reg2)); assert(isVectorRegister(reg3)); assert(insOptsScalableWords(opt)); + assert(insScalableOptsNone(sopt)); fmt = IF_SVE_AC_3A; break; @@ -8727,7 +8748,8 @@ void emitter::emitIns_R_R_R( assert(isVectorRegister(reg1)); assert(isLowPredicateRegister(reg2)); assert(isVectorRegister(reg3)); - assert(insOptsScalableSimple(opt)); + assert(insOptsScalableStandard(opt)); + assert(insScalableOptsNone(sopt)); fmt = IF_SVE_AD_3A; break; @@ -8737,7 +8759,8 @@ void emitter::emitIns_R_R_R( assert(isVectorRegister(reg1)); assert(isLowPredicateRegister(reg2)); assert(isVectorRegister(reg3)); - assert(insOptsScalableSimple(opt)); + assert(insOptsScalableStandard(opt)); + assert(insScalableOptsNone(sopt)); fmt = IF_SVE_AE_3A; break; @@ -8747,7 +8770,8 @@ void emitter::emitIns_R_R_R( assert(isFloatReg(reg1)); assert(isLowPredicateRegister(reg2)); assert(isVectorRegister(reg3)); - assert(insOptsScalableWithSimdScalar(opt)); + assert(insOptsScalableStandard(opt)); + assert(insScalableOptsNone(sopt)); fmt = IF_SVE_AF_3A; break; @@ -8758,7 +8782,8 @@ void emitter::emitIns_R_R_R( assert(isVectorRegister(reg1)); assert(isLowPredicateRegister(reg2)); assert(isVectorRegister(reg3)); - assert(insOptsScalableWithSimdVector(opt)); + assert(insOptsScalableStandard(opt)); + assert(insScalableOptsNone(sopt)); fmt = IF_SVE_AG_3A; break; @@ -8766,7 +8791,11 @@ void emitter::emitIns_R_R_R( assert(isVectorRegister(reg1)); assert(isLowPredicateRegister(reg2)); assert(isVectorRegister(reg3)); - assert(insOptsScalableSimple(opt) || insOptsScalableWithPredicateMerge(opt)); + assert(insOptsScalableStandard(opt)); + if (sopt == INS_SCALABLE_OPTS_PREDICATE_MERGE) + { + pmerge = true; + } fmt = IF_SVE_AH_3A; break; @@ -8775,7 +8804,8 @@ void emitter::emitIns_R_R_R( assert(isFloatReg(reg1)); assert(isLowPredicateRegister(reg2)); assert(isVectorRegister(reg3)); - assert(insOptsScalableWithSimdScalar(opt)); + assert(insOptsScalableWide(opt)); + assert(insScalableOptsNone(sopt)); fmt = IF_SVE_AI_3A; break; @@ -8784,7 +8814,8 @@ void emitter::emitIns_R_R_R( assert(isVectorRegister(reg1)); assert(isLowPredicateRegister(reg2)); assert(isVectorRegister(reg3)); - assert(insOptsScalableWithSimdVector(opt)); + assert(insOptsScalableStandard(opt)); + assert(insScalableOptsNone(sopt)); fmt = IF_SVE_AJ_3A; break; @@ -8795,7 +8826,8 @@ void emitter::emitIns_R_R_R( assert(isFloatReg(reg1)); assert(isLowPredicateRegister(reg2)); assert(isVectorRegister(reg3)); - assert(insOptsScalableWithSimdScalar(opt)); + assert(insOptsScalableStandard(opt)); + assert(insScalableOptsNone(sopt)); fmt = IF_SVE_AK_3A; break; @@ -8807,7 +8839,8 @@ void emitter::emitIns_R_R_R( assert(isVectorRegister(reg1)); assert(isLowPredicateRegister(reg2)); assert(isVectorRegister(reg3)); - assert(insOptsScalableWithSimdVector(opt)); + assert(insOptsScalableStandard(opt)); + assert(insScalableOptsNone(sopt)); fmt = IF_SVE_AL_3A; break; @@ -8817,7 +8850,8 @@ void emitter::emitIns_R_R_R( assert(isVectorRegister(reg1)); assert(isLowPredicateRegister(reg2)); assert(isVectorRegister(reg3)); - assert(insOptsScalableSimple(opt)); + assert(insOptsScalableStandard(opt)); + assert(insScalableOptsNone(sopt)); fmt = IF_SVE_AN_3A; break; @@ -8827,14 +8861,16 @@ void emitter::emitIns_R_R_R( assert(isVectorRegister(reg1)); assert(isLowPredicateRegister(reg2)); assert(isVectorRegister(reg3)); - if (insOptsScalableSimple(opt)) + if (sopt == INS_SCALABLE_OPTS_WIDE) { - fmt = IF_SVE_AN_3A; + assert(insOptsScalableWide(opt)); + fmt = IF_SVE_AO_3A; } else { - assert(insOptsScalableWide(opt)); - fmt = IF_SVE_AO_3A; + assert(insScalableOptsNone(sopt)); + assert(insOptsScalableStandard(opt)); + fmt = IF_SVE_AN_3A; } break; @@ -8846,7 +8882,8 @@ void emitter::emitIns_R_R_R( assert(isVectorRegister(reg1)); assert(isLowPredicateRegister(reg2)); assert(isVectorRegister(reg3)); - assert(insOptsScalableSimple(opt)); + assert(insOptsScalableStandard(opt)); + assert(insScalableOptsNone(sopt)); fmt = IF_SVE_AP_3A; break; @@ -8856,6 +8893,7 @@ void emitter::emitIns_R_R_R( assert(isLowPredicateRegister(reg2)); assert(isVectorRegister(reg3)); assert(insOptsScalableFloat(opt)); + assert(insScalableOptsNone(sopt)); fmt = IF_SVE_AP_3A; break; @@ -8864,7 +8902,8 @@ void emitter::emitIns_R_R_R( assert(isVectorRegister(reg1)); assert(isLowPredicateRegister(reg2)); assert(isVectorRegister(reg3)); - assert(insOptsScalableSimple(opt)); + assert(insOptsScalableStandard(opt)); + assert(insScalableOptsNone(sopt)); fmt = IF_SVE_AQ_3A; break; @@ -8874,6 +8913,7 @@ void emitter::emitIns_R_R_R( assert(isLowPredicateRegister(reg2)); assert(isVectorRegister(reg3)); assert(insOptsScalableAtLeastHalf(opt)); + assert(insScalableOptsNone(sopt)); fmt = IF_SVE_AQ_3A; break; @@ -8883,6 +8923,7 @@ void emitter::emitIns_R_R_R( assert(isLowPredicateRegister(reg2)); assert(isVectorRegister(reg3)); assert(insOptsScalableWords(opt)); + assert(insScalableOptsNone(sopt)); fmt = IF_SVE_AQ_3A; break; @@ -8892,6 +8933,7 @@ void emitter::emitIns_R_R_R( assert(isLowPredicateRegister(reg2)); assert(isVectorRegister(reg3)); assert(opt == INS_OPTS_SCALABLE_D); + assert(insScalableOptsNone(sopt)); fmt = IF_SVE_AQ_3A; break; @@ -8900,19 +8942,22 @@ void emitter::emitIns_R_R_R( assert(isLowPredicateRegister(reg2)); assert(isVectorRegister(reg3)); assert(insOptsScalableWords(opt)); + assert(insScalableOptsNone(sopt)); fmt = IF_SVE_CL_3A; break; case INS_sve_clasta: case INS_sve_clastb: + assert(insOptsScalableStandard(opt)); assert(isLowPredicateRegister(reg2)); assert(isVectorRegister(reg3)); - if (insOptsScalableSimple(opt)) + if (isGeneralRegister(reg1)) { - assert(isVectorRegister(reg1)); - fmt = IF_SVE_CM_3A; + assert(insScalableOptsNone(sopt)); + assert(isValidScalarDatasize(size)); + fmt = IF_SVE_CO_3A; } - else if (insOptsScalableWithSimdScalar(opt)) + else if (sopt == INS_SCALABLE_OPTS_WITH_SIMD_SCALAR) { assert(isFloatReg(reg1)); assert(isValidVectorElemsize(size)); @@ -8920,55 +8965,58 @@ void emitter::emitIns_R_R_R( } else { - assert(insOptsScalableWithScalar(opt)); - assert(isGeneralRegister(reg1)); - assert(isValidScalarDatasize(size)); - fmt = IF_SVE_CO_3A; + assert(insScalableOptsNone(sopt)); + assert(isVectorRegister(reg1)); + fmt = IF_SVE_CM_3A; } break; case INS_sve_cpy: case INS_sve_mov: + assert(insOptsScalableStandard(opt)); assert(isVectorRegister(reg1)); assert(isLowPredicateRegister(reg2)); - if (insOptsScalableWithSimdScalar(opt)) + if (isGeneralRegisterOrSP(reg3)) { - assert(isVectorRegister(reg3)); - fmt = IF_SVE_CP_3A; + assert(insScalableOptsNone(sopt)); + fmt = IF_SVE_CQ_3A; + reg3 = encodingSPtoZR(reg3); } else { - assert(insOptsScalableWithScalar(opt)); - assert(isGeneralRegisterOrSP(reg3)); - fmt = IF_SVE_CQ_3A; - reg3 = encodingSPtoZR(reg3); + assert(sopt == INS_SCALABLE_OPTS_WITH_SIMD_SCALAR); + assert(isVectorRegister(reg3)); + fmt = IF_SVE_CP_3A; } + // MOV is an alias for CPY, and is always the preferred disassembly. ins = INS_sve_mov; break; case INS_sve_lasta: case INS_sve_lastb: + assert(insOptsScalableStandard(opt)); assert(isLowPredicateRegister(reg2)); assert(isVectorRegister(reg3)); - if (insOptsScalableWithSimdScalar(opt)) - { - assert(isVectorRegister(reg1)); - fmt = IF_SVE_CR_3A; - } - else + if (isGeneralRegister(reg1)) { - assert(insOptsScalableWithScalar(opt)); + assert(insScalableOptsNone(sopt)); assert(isGeneralRegister(reg1)); fmt = IF_SVE_CS_3A; } + else if (sopt == INS_SCALABLE_OPTS_WITH_SIMD_SCALAR) + { + assert(isVectorRegister(reg1)); + fmt = IF_SVE_CR_3A; + } break; case INS_sve_rbit: assert(isVectorRegister(reg1)); assert(isLowPredicateRegister(reg2)); assert(isVectorRegister(reg3)); - assert(insOptsScalableSimple(opt)); + assert(insOptsScalableStandard(opt)); + assert(insScalableOptsNone(sopt)); fmt = IF_SVE_CU_3A; break; @@ -8977,6 +9025,7 @@ void emitter::emitIns_R_R_R( assert(isLowPredicateRegister(reg2)); assert(isVectorRegister(reg3)); assert(insOptsScalableAtLeastHalf(opt)); + assert(insScalableOptsNone(sopt)); fmt = IF_SVE_CU_3A; break; @@ -8985,6 +9034,7 @@ void emitter::emitIns_R_R_R( assert(isLowPredicateRegister(reg2)); assert(isVectorRegister(reg3)); assert(insOptsScalableWords(opt)); + assert(insScalableOptsNone(sopt)); fmt = IF_SVE_CU_3A; break; @@ -8993,6 +9043,7 @@ void emitter::emitIns_R_R_R( assert(isLowPredicateRegister(reg2)); assert(isVectorRegister(reg3)); assert(opt == INS_OPTS_SCALABLE_D); + assert(insScalableOptsNone(sopt)); fmt = IF_SVE_CU_3A; break; @@ -9007,7 +9058,8 @@ void emitter::emitIns_R_R_R( assert(isVectorRegister(reg1)); assert(isLowPredicateRegister(reg2)); assert(isVectorRegister(reg3)); - assert(insOptsScalableSimple(opt)); + assert(insOptsScalableStandard(opt)); + assert(insScalableOptsNone(sopt)); fmt = IF_SVE_EP_3A; break; @@ -9017,6 +9069,7 @@ void emitter::emitIns_R_R_R( assert(isLowPredicateRegister(reg2)); assert(isVectorRegister(reg3)); assert(insOptsScalableAtLeastHalf(opt)); + assert(insScalableOptsNone(sopt)); fmt = IF_SVE_EQ_3A; break; @@ -9028,7 +9081,8 @@ void emitter::emitIns_R_R_R( assert(isVectorRegister(reg1)); assert(isLowPredicateRegister(reg2)); assert(isVectorRegister(reg3)); - assert(insOptsScalableSimple(opt)); + assert(insOptsScalableStandard(opt)); + assert(insScalableOptsNone(sopt)); fmt = IF_SVE_ER_3A; break; @@ -9037,7 +9091,8 @@ void emitter::emitIns_R_R_R( assert(isVectorRegister(reg1)); assert(isLowPredicateRegister(reg2)); assert(isVectorRegister(reg3)); - assert(insOptsScalableSimple(opt)); + assert(insOptsScalableStandard(opt)); + assert(insScalableOptsNone(sopt)); fmt = IF_SVE_ES_3A; break; @@ -9047,6 +9102,7 @@ void emitter::emitIns_R_R_R( assert(isLowPredicateRegister(reg2)); assert(isVectorRegister(reg3)); assert(opt == INS_OPTS_SCALABLE_S); + assert(insScalableOptsNone(sopt)); fmt = IF_SVE_ES_3A; break; @@ -9061,7 +9117,8 @@ void emitter::emitIns_R_R_R( assert(isVectorRegister(reg1)); assert(isLowPredicateRegister(reg2)); assert(isVectorRegister(reg3)); - assert(insOptsScalableSimple(opt)); + assert(insOptsScalableStandard(opt)); + assert(insScalableOptsNone(sopt)); fmt = IF_SVE_ET_3A; break; @@ -9080,7 +9137,8 @@ void emitter::emitIns_R_R_R( assert(isVectorRegister(reg1)); assert(isLowPredicateRegister(reg2)); assert(isVectorRegister(reg3)); - assert(insOptsScalableSimple(opt)); + assert(insOptsScalableStandard(opt)); + assert(insScalableOptsNone(sopt)); fmt = IF_SVE_EU_3A; break; @@ -9093,6 +9151,7 @@ void emitter::emitIns_R_R_R( assert(isLowPredicateRegister(reg2)); assert(isVectorRegister(reg3)); assert(insOptsScalableFloat(opt)); + assert(insScalableOptsNone(sopt)); fmt = IF_SVE_GR_3A; break; @@ -9105,7 +9164,8 @@ void emitter::emitIns_R_R_R( assert(isVectorRegister(reg1)); assert(isLowPredicateRegister(reg2)); assert(isVectorRegister(reg3)); - assert(insOptsScalableWithSimdVector(opt)); + assert(insOptsScalableFloat(opt)); + assert(insScalableOptsNone(sopt)); fmt = IF_SVE_GS_3A; break; @@ -9117,8 +9177,9 @@ void emitter::emitIns_R_R_R( assert(isFloatReg(reg1)); assert(isLowPredicateRegister(reg2)); assert(isVectorRegister(reg3)); - assert(insOptsScalableWithSimdFPScalar(opt)); + assert(insOptsScalableFloat(opt)); assert(isValidVectorElemsizeSveFloat(size)); + assert(insScalableOptsNone(sopt)); fmt = IF_SVE_HE_3A; break; @@ -9126,8 +9187,9 @@ void emitter::emitIns_R_R_R( assert(isFloatReg(reg1)); assert(isLowPredicateRegister(reg2)); assert(isVectorRegister(reg3)); - assert(insOptsScalableWithSimdFPScalar(opt)); + assert(insOptsScalableFloat(opt)); assert(isValidVectorElemsizeSveFloat(size)); + assert(insScalableOptsNone(sopt)); fmt = IF_SVE_HJ_3A; break; @@ -9148,6 +9210,7 @@ void emitter::emitIns_R_R_R( assert(isLowPredicateRegister(reg2)); assert(isVectorRegister(reg3)); assert(insOptsScalableFloat(opt)); + assert(insScalableOptsNone(sopt)); fmt = IF_SVE_HL_3A; break; @@ -9158,6 +9221,7 @@ void emitter::emitIns_R_R_R( assert(isLowPredicateRegister(reg2)); assert(isVectorRegister(reg3)); assert(insOptsScalableFloat(opt)); + assert(insScalableOptsNone(sopt)); fmt = IF_SVE_HL_3A; break; @@ -9172,6 +9236,7 @@ void emitter::emitIns_R_R_R( assert(isLowPredicateRegister(reg2)); assert(isVectorRegister(reg3)); assert(insOptsScalableFloat(opt)); + assert(insScalableOptsNone(sopt)); fmt = IF_SVE_HQ_3A; break; @@ -9181,6 +9246,7 @@ void emitter::emitIns_R_R_R( assert(isLowPredicateRegister(reg2)); assert(isVectorRegister(reg3)); assert(insOptsScalableFloat(opt)); + assert(insScalableOptsNone(sopt)); fmt = IF_SVE_HR_3A; break; @@ -9202,6 +9268,11 @@ void emitter::emitIns_R_R_R( id->idReg2(reg2); id->idReg3(reg3); + if (pmerge) + { + id->idPredicateReg2Merge(pmerge); + } + dispIns(id); appendToCurIG(id); } @@ -9681,7 +9752,7 @@ void emitter::emitIns_R_R_R_I(instruction ins, break; case INS_sve_ld1b: - assert(insOptsScalableSimple(opt)); + assert(insOptsScalableStandard(opt)); assert(isVectorRegister(reg1)); assert(isPredicateRegister(reg2)); assert(isGeneralRegister(reg3)); @@ -9738,7 +9809,7 @@ void emitter::emitIns_R_R_R_I(instruction ins, break; case INS_sve_ldnf1b: - assert(insOptsScalableSimple(opt)); + assert(insOptsScalableStandard(opt)); assert(isVectorRegister(reg1)); assert(isPredicateRegister(reg2)); assert(isGeneralRegister(reg3)); @@ -9750,7 +9821,7 @@ void emitter::emitIns_R_R_R_I(instruction ins, case INS_sve_ldnt1h: case INS_sve_ldnt1w: case INS_sve_ldnt1d: - assert(insOptsScalableSimple(opt)); + assert(insOptsScalableStandard(opt)); assert(isVectorRegister(reg1)); assert(isPredicateRegister(reg2)); assert(isGeneralRegister(reg3)); @@ -9792,7 +9863,7 @@ void emitter::emitIns_R_R_R_I(instruction ins, case INS_sve_ld1row: case INS_sve_ld1rqd: case INS_sve_ld1rod: - assert(insOptsScalableSimple(opt)); + assert(insOptsScalableStandard(opt)); assert(isVectorRegister(reg1)); assert(isPredicateRegister(reg2)); assert(isGeneralRegister(reg3)); @@ -9894,7 +9965,7 @@ void emitter::emitIns_R_R_R_I(instruction ins, case INS_sve_ld2d: case INS_sve_ld3d: case INS_sve_ld4d: - assert(insOptsScalableSimple(opt)); + assert(insOptsScalableStandard(opt)); assert(isVectorRegister(reg1)); assert(isPredicateRegister(reg2)); assert(isGeneralRegister(reg3)); @@ -9999,7 +10070,7 @@ void emitter::emitIns_R_R_R_I(instruction ins, case INS_sve_stnt1h: case INS_sve_stnt1w: case INS_sve_stnt1d: - assert(insOptsScalableSimple(opt)); + assert(insOptsScalableStandard(opt)); assert(isVectorRegister(reg1)); assert(isPredicateRegister(reg2)); assert(isGeneralRegister(reg3)); @@ -10072,7 +10143,7 @@ void emitter::emitIns_R_R_R_I(instruction ins, case INS_sve_st2d: case INS_sve_st3d: case INS_sve_st4d: - assert(insOptsScalableSimple(opt)); + assert(insOptsScalableStandard(opt)); assert(isVectorRegister(reg1)); assert(isPredicateRegister(reg2)); assert(isGeneralRegister(reg3)); @@ -10598,7 +10669,7 @@ void emitter::emitIns_R_R_R_R(instruction ins, case INS_sve_cmplo: case INS_sve_cmpls: case INS_sve_cmplt: - assert(insOptsScalableSimple(opt)); + assert(insOptsScalableStandard(opt)); assert(isPredicateRegister(reg1)); // DDDD assert(isLowPredicateRegister(reg2)); // ggg assert(isVectorRegister(reg3)); // mmmmm @@ -10609,7 +10680,7 @@ void emitter::emitIns_R_R_R_R(instruction ins, case INS_sve_mla: case INS_sve_mls: - assert(insOptsScalableSimple(opt)); + assert(insOptsScalableStandard(opt)); assert(isVectorRegister(reg1)); // ddddd assert(isLowPredicateRegister(reg2)); // ggg assert(isVectorRegister(reg3)); // nnnnn @@ -10620,7 +10691,7 @@ void emitter::emitIns_R_R_R_R(instruction ins, case INS_sve_mad: case INS_sve_msb: - assert(insOptsScalableSimple(opt)); + assert(insOptsScalableStandard(opt)); assert(isVectorRegister(reg1)); // ddddd assert(isLowPredicateRegister(reg2)); // ggg assert(isVectorRegister(reg3)); // mmmmm @@ -16033,11 +16104,11 @@ size_t emitter::emitOutputInstr(insGroup* ig, instrDesc* id, BYTE** dp) // Scalable with Merge or Zero predicate case IF_SVE_AH_3A: // ........xx.....M ...gggnnnnnddddd -- SVE constructive prefix (predicated) code = emitInsCodeSve(ins, fmt); - code |= insEncodeReg_V_4_to_0(id->idReg1()); // nnnnn - code |= insEncodeReg_P_12_to_10(id->idReg2()); // ggg - code |= insEncodeReg_V_9_to_5(id->idReg3()); // ddddd - code |= insEncodePredQualifier_16(insOptsScalableWithPredicateMerge(id->idInsOpt())); // M - code |= insEncodeSveElemsize(optGetSveElemsize(id->idInsOpt())); // xx + code |= insEncodeReg_V_4_to_0(id->idReg1()); // nnnnn + code |= insEncodeReg_P_12_to_10(id->idReg2()); // ggg + code |= insEncodeReg_V_9_to_5(id->idReg3()); // ddddd + code |= insEncodePredQualifier_16(id->idPredicateReg2Merge()); // M + code |= insEncodeSveElemsize(optGetSveElemsize(id->idInsOpt())); // xx dst += emitOutput_Instr(dst, code); break; @@ -16932,55 +17003,36 @@ void emitter::emitDispArrangement(insOpts opt) str = "8b"; break; case INS_OPTS_16B: - case INS_OPTS_SCALABLE_B_WITH_SIMD_VECTOR: str = "16b"; break; case INS_OPTS_SCALABLE_B: - case INS_OPTS_SCALABLE_WIDE_B: - case INS_OPTS_SCALABLE_B_WITH_SIMD_SCALAR: - case INS_OPTS_SCALABLE_B_WITH_SCALAR: - case INS_OPTS_SCALABLE_B_WITH_PREDICATE_MERGE: str = "b"; break; case INS_OPTS_4H: str = "4h"; break; case INS_OPTS_8H: - case INS_OPTS_SCALABLE_H_WITH_SIMD_VECTOR: str = "8h"; break; case INS_OPTS_SCALABLE_H: - case INS_OPTS_SCALABLE_WIDE_H: - case INS_OPTS_SCALABLE_H_WITH_SIMD_SCALAR: - case INS_OPTS_SCALABLE_H_WITH_SCALAR: - case INS_OPTS_SCALABLE_H_WITH_PREDICATE_MERGE: str = "h"; break; case INS_OPTS_2S: str = "2s"; break; case INS_OPTS_4S: - case INS_OPTS_SCALABLE_S_WITH_SIMD_VECTOR: str = "4s"; break; case INS_OPTS_SCALABLE_S: - case INS_OPTS_SCALABLE_WIDE_S: - case INS_OPTS_SCALABLE_S_WITH_SIMD_SCALAR: - case INS_OPTS_SCALABLE_S_WITH_SCALAR: - case INS_OPTS_SCALABLE_S_WITH_PREDICATE_MERGE: str = "s"; break; case INS_OPTS_1D: str = "1d"; break; case INS_OPTS_2D: - case INS_OPTS_SCALABLE_D_WITH_SIMD_VECTOR: str = "2d"; break; case INS_OPTS_SCALABLE_D: - case INS_OPTS_SCALABLE_D_WITH_SIMD_SCALAR: - case INS_OPTS_SCALABLE_D_WITH_SCALAR: - case INS_OPTS_SCALABLE_D_WITH_PREDICATE_MERGE: str = "d"; break; case INS_OPTS_SCALABLE_Q: @@ -18571,8 +18623,7 @@ void emitter::emitDispInsHelp( // ., /, . case IF_SVE_AH_3A: // ........xx.....M ...gggnnnnnddddd -- SVE constructive prefix (predicated) { - PredicateType ptype = - (insOptsScalableWithPredicateMerge(id->idInsOpt())) ? PREDICATE_MERGE : PREDICATE_ZERO; + PredicateType ptype = (id->idPredicateReg2Merge()) ? PREDICATE_MERGE : PREDICATE_ZERO; emitDispSveReg(id->idReg1(), id->idInsOpt(), true); // nnnnn emitDispLowPredicateReg(id->idReg2(), ptype, id->idInsOpt(), true); // ggg emitDispSveReg(id->idReg3(), id->idInsOpt(), false); // ddddd @@ -18643,9 +18694,9 @@ void emitter::emitDispInsHelp( case IF_SVE_AJ_3A: // ........xx...... ...gggnnnnnddddd -- SVE integer add reduction (quadwords) case IF_SVE_AL_3A: // ........xx...... ...gggnnnnnddddd -- SVE integer min/max reduction (quadwords) case IF_SVE_GS_3A: // ........xx...... ...gggnnnnnddddd -- SVE floating-point recursive reduction (quadwords) - emitDispVectorReg(id->idReg1(), id->idInsOpt(), true); // ddddd - emitDispPredicateReg(id->idReg2(), PREDICATE_NONE, id->idInsOpt(), true); // ggg - emitDispSveReg(id->idReg3(), id->idInsOpt(), false); // mmmmm + emitDispVectorReg(id->idReg1(), optSveToQuadwordElemsizeArrangement(id->idInsOpt()), true); // ddddd + emitDispPredicateReg(id->idReg2(), PREDICATE_NONE, id->idInsOpt(), true); // ggg + emitDispSveReg(id->idReg3(), id->idInsOpt(), false); // mmmmm break; //
, , . diff --git a/src/coreclr/jit/emitarm64.h b/src/coreclr/jit/emitarm64.h index c35c5a5f93c91..12650ee664c07 100644 --- a/src/coreclr/jit/emitarm64.h +++ b/src/coreclr/jit/emitarm64.h @@ -666,6 +666,9 @@ static insOpts optWidenElemsizeArrangement(insOpts arrangement); // element. static insOpts optWidenSveElemsizeArrangement(insOpts arrangement); +// For the given SVE 'arrangement', return the one when reduced to a quadword vector. +static insOpts optSveToQuadwordElemsizeArrangement(insOpts arrangement); + // For the given 'datasize' returns the one that is double that of the 'datasize'. static emitAttr widenDatasize(emitAttr datasize); @@ -962,90 +965,51 @@ inline static bool insOptsConvertIntToFloat(insOpts opt) inline static bool insOptsScalable(insOpts opt) { - // Opt is any of the scalable types. - return ((insOptsScalableSimple(opt)) || (insOptsScalableWide(opt)) || (insOptsScalableWithSimdScalar(opt)) || - (insOptsScalableWithScalar(opt)) || (insOptsScalableWithSimdVector(opt)) || (opt == INS_OPTS_SCALABLE_Q) || - insOptsScalableWithPredicateMerge(opt)); + // `opt` is any of the scalable types. + return ((opt == INS_OPTS_SCALABLE_B) || (opt == INS_OPTS_SCALABLE_H) || (opt == INS_OPTS_SCALABLE_S) || + (opt == INS_OPTS_SCALABLE_D) || (opt == INS_OPTS_SCALABLE_Q)); } -inline static bool insOptsScalableSimple(insOpts opt) +inline static bool insOptsScalableStandard(insOpts opt) { - // `opt` is any of the standard scalable types. + // `opt` is any of the scalable types, except Quadword. return ((opt == INS_OPTS_SCALABLE_B) || (opt == INS_OPTS_SCALABLE_H) || (opt == INS_OPTS_SCALABLE_S) || (opt == INS_OPTS_SCALABLE_D)); } inline static bool insOptsScalableWords(insOpts opt) { - // `opt` is any of the standard word and above scalable types. + // `opt` is any of the word and above scalable types. return ((opt == INS_OPTS_SCALABLE_S) || (opt == INS_OPTS_SCALABLE_D)); } inline static bool insOptsScalableWordsOrQuadwords(insOpts opt) { - // `opt` is any of the standard word, quadword and above scalable types. + // `opt` is any of the word, quadword and above scalable types. return (insOptsScalableWords(opt) || (opt == INS_OPTS_SCALABLE_Q)); } inline static bool insOptsScalableAtLeastHalf(insOpts opt) { - // `opt` is any of the standard half and above scalable types. + // `opt` is any of the half and above scalable types. return ((opt == INS_OPTS_SCALABLE_H) || (opt == INS_OPTS_SCALABLE_S) || (opt == INS_OPTS_SCALABLE_D)); } inline static bool insOptsScalableFloat(insOpts opt) { - // `opt` is any of the standard scalable types that are valid for FP. + // `opt` is any of the scalable types that are valid for FP. return ((opt == INS_OPTS_SCALABLE_H) || (opt == INS_OPTS_SCALABLE_S) || (opt == INS_OPTS_SCALABLE_D)); } inline static bool insOptsScalableWide(insOpts opt) { // `opt` is any of the scalable types that are valid for widening to size D. - return ((opt == INS_OPTS_SCALABLE_WIDE_B) || (opt == INS_OPTS_SCALABLE_WIDE_H) || - (opt == INS_OPTS_SCALABLE_WIDE_S)); -} - -inline static bool insOptsScalableWithSimdVector(insOpts opt) -{ - // `opt` is any of the scalable types that are valid for conversion to an Advsimd SIMD Vector. - return ((opt == INS_OPTS_SCALABLE_B_WITH_SIMD_VECTOR) || (opt == INS_OPTS_SCALABLE_H_WITH_SIMD_VECTOR) || - (opt == INS_OPTS_SCALABLE_S_WITH_SIMD_VECTOR) || (opt == INS_OPTS_SCALABLE_D_WITH_SIMD_VECTOR)); -} - -inline static bool insOptsScalableWithSimdScalar(insOpts opt) -{ - // `opt` is any of the scalable types that are valid for conversion to/from a scalar in a SIMD register. - return ((opt == INS_OPTS_SCALABLE_B_WITH_SIMD_SCALAR) || (opt == INS_OPTS_SCALABLE_H_WITH_SIMD_SCALAR) || - (opt == INS_OPTS_SCALABLE_S_WITH_SIMD_SCALAR) || (opt == INS_OPTS_SCALABLE_D_WITH_SIMD_SCALAR)); -} - -inline static bool insOptsScalableWithSimdFPScalar(insOpts opt) -{ - // `opt` is any of the scalable types that are valid for conversion to/from a FP scalar in a SIMD register. - return ((opt == INS_OPTS_SCALABLE_H_WITH_SIMD_SCALAR) || (opt == INS_OPTS_SCALABLE_S_WITH_SIMD_SCALAR) || - (opt == INS_OPTS_SCALABLE_D_WITH_SIMD_SCALAR)); -} - -inline static bool insOptsScalableWideningToSimdScalar(insOpts opt) -{ - // `opt` is any of the scalable types that are valid for widening then conversion to a scalar in a SIMD register. - return ((opt == INS_OPTS_SCALABLE_B_WITH_SIMD_SCALAR) || (opt == INS_OPTS_SCALABLE_H_WITH_SIMD_SCALAR) || - (opt == INS_OPTS_SCALABLE_S_WITH_SIMD_SCALAR)); -} - -inline static bool insOptsScalableWithScalar(insOpts opt) -{ - // `opt` is any of the SIMD scalable types that are valid for conversion to/from a scalar. - return ((opt == INS_OPTS_SCALABLE_B_WITH_SCALAR) || (opt == INS_OPTS_SCALABLE_H_WITH_SCALAR) || - (opt == INS_OPTS_SCALABLE_S_WITH_SCALAR) || (opt == INS_OPTS_SCALABLE_D_WITH_SCALAR)); + return ((opt == INS_OPTS_SCALABLE_B) || (opt == INS_OPTS_SCALABLE_H) || (opt == INS_OPTS_SCALABLE_S)); } -inline static bool insOptsScalableWithPredicateMerge(insOpts opt) +inline static bool insScalableOptsNone(insScalableOpts sopt) { - // `opt` is any of the SIMD scalable types that are valid for use with a merge predicate. - return ((opt == INS_OPTS_SCALABLE_B_WITH_PREDICATE_MERGE) || (opt == INS_OPTS_SCALABLE_H_WITH_PREDICATE_MERGE) || - (opt == INS_OPTS_SCALABLE_S_WITH_PREDICATE_MERGE) || (opt == INS_OPTS_SCALABLE_D_WITH_PREDICATE_MERGE)); + return sopt == INS_SCALABLE_OPTS_NONE; } static bool isValidImmCond(ssize_t imm); @@ -1108,8 +1072,13 @@ void emitIns_R_R_I( // Checks for a large immediate that needs a second instruction void emitIns_R_R_Imm(instruction ins, emitAttr attr, regNumber reg1, regNumber reg2, ssize_t imm); -void emitIns_R_R_R( - instruction ins, emitAttr attr, regNumber reg1, regNumber reg2, regNumber reg3, insOpts opt = INS_OPTS_NONE); +void emitIns_R_R_R(instruction ins, + emitAttr attr, + regNumber reg1, + regNumber reg2, + regNumber reg3, + insOpts opt = INS_OPTS_NONE, + insScalableOpts sopt = INS_SCALABLE_OPTS_NONE); void emitIns_R_R_R_I(instruction ins, emitAttr attr, diff --git a/src/coreclr/jit/instr.h b/src/coreclr/jit/instr.h index 3579c3ecf5850..e24d25cd5f606 100644 --- a/src/coreclr/jit/instr.h +++ b/src/coreclr/jit/instr.h @@ -276,30 +276,6 @@ enum insOpts : unsigned INS_OPTS_SCALABLE_D, INS_OPTS_SCALABLE_Q, - INS_OPTS_SCALABLE_WIDE_B, - INS_OPTS_SCALABLE_WIDE_H, - INS_OPTS_SCALABLE_WIDE_S, - - INS_OPTS_SCALABLE_B_WITH_SIMD_VECTOR, - INS_OPTS_SCALABLE_H_WITH_SIMD_VECTOR, - INS_OPTS_SCALABLE_S_WITH_SIMD_VECTOR, - INS_OPTS_SCALABLE_D_WITH_SIMD_VECTOR, - - INS_OPTS_SCALABLE_B_WITH_SIMD_SCALAR, - INS_OPTS_SCALABLE_H_WITH_SIMD_SCALAR, - INS_OPTS_SCALABLE_S_WITH_SIMD_SCALAR, - INS_OPTS_SCALABLE_D_WITH_SIMD_SCALAR, - - INS_OPTS_SCALABLE_B_WITH_SCALAR, - INS_OPTS_SCALABLE_H_WITH_SCALAR, - INS_OPTS_SCALABLE_S_WITH_SCALAR, - INS_OPTS_SCALABLE_D_WITH_SCALAR, - - INS_OPTS_SCALABLE_B_WITH_PREDICATE_MERGE, - INS_OPTS_SCALABLE_H_WITH_PREDICATE_MERGE, - INS_OPTS_SCALABLE_S_WITH_PREDICATE_MERGE, - INS_OPTS_SCALABLE_D_WITH_PREDICATE_MERGE, - INS_OPTS_MSL, // Vector Immediate (shifting ones variant) INS_OPTS_S_TO_4BYTE, // Single to INT32 @@ -328,6 +304,17 @@ enum insOpts : unsigned #endif }; +// When a single instruction has different encodings variants, this is used +// to distinguish those that can't be determined soley by register usage. +enum insScalableOpts : unsigned +{ + INS_SCALABLE_OPTS_NONE, // No Variants exist + + INS_SCALABLE_OPTS_WIDE, // Variants with wide elements (eg asr) + INS_SCALABLE_OPTS_WITH_SIMD_SCALAR, // Variants with a NEON SIMD register (eg clasta) + INS_SCALABLE_OPTS_PREDICATE_MERGE, // Variants with a Pg/M predicate (eg brka) +}; + enum insCond : unsigned { INS_COND_EQ,