diff --git a/ChocolArm64/AOpCodeTable.cs b/ChocolArm64/AOpCodeTable.cs index c0c38bb39..fcaee3847 100644 --- a/ChocolArm64/AOpCodeTable.cs +++ b/ChocolArm64/AOpCodeTable.cs @@ -347,6 +347,8 @@ namespace ChocolArm64 SetA64("0x001110101xxxxx000111xxxxxxxxxx", AInstEmit.Orr_V, typeof(AOpCodeSimdReg)); SetA64("0x00111100000xxx< Context.Emit(OpCodes.Or)); } + public static void Rev16_V(AILEmitterCtx Context) + { + EmitRev_V(Context, ContainerSize: 1); + } + + public static void Rev32_V(AILEmitterCtx Context) + { + EmitRev_V(Context, ContainerSize: 2); + } + public static void Rev64_V(AILEmitterCtx Context) + { + EmitRev_V(Context, ContainerSize: 3); + } + + private static void EmitRev_V(AILEmitterCtx Context, int ContainerSize) { AOpCodeSimd Op = (AOpCodeSimd)Context.CurrOp; @@ -152,15 +168,25 @@ namespace ChocolArm64.Instruction int Elems = Bytes >> Op.Size; - int RevIndex = Elems - 1; + if (Op.Size >= ContainerSize) + { + throw new InvalidOperationException(); + } + + int ContainerMask = (1 << (ContainerSize - Op.Size)) - 1; for (int Index = 0; Index < (Bytes >> Op.Size); Index++) { - EmitVectorExtractZx(Context, Op.Rn, RevIndex--, Op.Size); + int RevIndex = Index ^ ContainerMask; - EmitVectorInsert(Context, Op.Rd, Index, Op.Size); + EmitVectorExtractZx(Context, Op.Rn, RevIndex, Op.Size); + + EmitVectorInsertTmp(Context, Index, Op.Size); } + Context.EmitLdvectmp(); + Context.EmitStvec(Op.Rd); + if (Op.RegisterSize == ARegisterSize.SIMD64) { EmitVectorZeroUpper(Context, Op.Rd);