@@ -1196,6 +1196,9 @@ static guint16 sri_vector_methods [] = {
11961196 SN_AsUInt64 ,
11971197 SN_AsVector ,
11981198 SN_AsVector128 ,
1199+ SN_AsVector128Unsafe ,
1200+ SN_AsVector2 ,
1201+ SN_AsVector3 ,
11991202 SN_AsVector4 ,
12001203 SN_BitwiseAnd ,
12011204 SN_BitwiseOr ,
@@ -1640,7 +1643,11 @@ emit_sri_vector (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSignature *fsi
16401643 }
16411644 case SN_AsVector :
16421645 case SN_AsVector128 :
1643- case SN_AsVector4 : {
1646+ case SN_AsVector128Unsafe :
1647+ case SN_AsVector2 :
1648+ case SN_AsVector3 :
1649+ case SN_AsVector4 :
1650+ case SN_AsVector4Unsafe : {
16441651 if (!is_element_type_primitive (fsig -> ret ) || !is_element_type_primitive (fsig -> params [0 ]))
16451652 return NULL ;
16461653
@@ -1650,10 +1657,54 @@ emit_sri_vector (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSignature *fsi
16501657 MonoClass * arg_class = mono_class_from_mono_type_internal (fsig -> params [0 ]);
16511658 int arg_size = mono_class_value_size (arg_class , NULL );
16521659
1653- if (arg_size == ret_size )
1660+ if (arg_size == ret_size ) {
16541661 return emit_simd_ins (cfg , klass , OP_XCAST , args [0 ]-> dreg , -1 );
1662+ }
16551663
1656- return NULL ;
1664+ if ((ret_size != 8 ) && (ret_size != 12 ) && (ret_size != 16 )) {
1665+ return NULL ;
1666+ }
1667+
1668+ if ((arg_size != 8 ) && (arg_size != 12 ) && (arg_size != 16 )) {
1669+ return NULL ;
1670+ }
1671+
1672+ bool isUnsafe = (id == SN_AsVector128Unsafe ) || (id == SN_AsVector4Unsafe );
1673+
1674+ if (arg_size > ret_size ) {
1675+ #ifdef TARGET_ARM64
1676+ if (ret_size == 8 ) {
1677+ return emit_simd_ins_for_sig (cfg , klass , OP_XLOWER , 0 , arg0_type , fsig , args );
1678+ }
1679+ #endif
1680+ return emit_simd_ins (cfg , klass , OP_XCAST , args [0 ]-> dreg , -1 );
1681+ } else {
1682+ #ifdef TARGET_ARM64
1683+ if (arg_size == 8 ) {
1684+ int op = isUnsafe ? OP_XWIDEN : OP_XWIDEN_UNSAFE ;
1685+ return emit_simd_ins_for_sig (cfg , klass , op , 0 , arg0_type , fsig , args );
1686+ }
1687+ #endif
1688+ MonoInst * ins = args [0 ];
1689+
1690+ if (!isUnsafe ) {
1691+ static float r4_0 = 0 ;
1692+ MonoInst * zero ;
1693+ int zero_dreg = alloc_freg (cfg );
1694+ MONO_INST_NEW (cfg , zero , OP_R4CONST );
1695+ zero -> inst_p0 = (void * )& r4_0 ;
1696+ zero -> dreg = zero_dreg ;
1697+ MONO_ADD_INS (cfg -> cbb , zero );
1698+
1699+ if (arg_size == 8 ) {
1700+ ins = emit_vector_insert_element (cfg , klass , ins , MONO_TYPE_R4 , zero , 2 , FALSE);
1701+ }
1702+ if (ret_size == 16 ) {
1703+ ins = emit_vector_insert_element (cfg , klass , ins , MONO_TYPE_R4 , zero , 3 , FALSE);
1704+ }
1705+ }
1706+ return emit_simd_ins (cfg , klass , OP_XCAST , ins -> dreg , -1 );
1707+ }
16571708 }
16581709 case SN_Ceiling :
16591710 case SN_Floor : {
0 commit comments