aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorgdkchan <gab.dark.100@gmail.com>2018-06-25 18:40:55 -0300
committergdkchan <gab.dark.100@gmail.com>2018-06-25 18:40:55 -0300
commit37a6e84fd49a4e73747281e92d795c5401be901e (patch)
treebe0deff4b27f9c57c450ce2146bee919059d23b2
parent8f4cd35ade6204aac01ecee9f4303a4e9ac191a4 (diff)
Add REV16/32 (vector) instructions and fix REV64
-rw-r--r--ChocolArm64/AOpCodeTable.cs2
-rw-r--r--ChocolArm64/Instruction/AInstEmitSimdLogical.cs32
2 files changed, 31 insertions, 3 deletions
diff --git a/ChocolArm64/AOpCodeTable.cs b/ChocolArm64/AOpCodeTable.cs
index c0c38bb3..fcaee384 100644
--- a/ChocolArm64/AOpCodeTable.cs
+++ b/ChocolArm64/AOpCodeTable.cs
@@ -347,6 +347,8 @@ namespace ChocolArm64
SetA64("0x001110101xxxxx000111xxxxxxxxxx", AInstEmit.Orr_V, typeof(AOpCodeSimdReg));
SetA64("0x00111100000xxx<<x101xxxxxxxxxx", AInstEmit.Orr_Vi, typeof(AOpCodeSimdImm));
SetA64("0x101110<<1xxxxx010000xxxxxxxxxx", AInstEmit.Raddhn_V, typeof(AOpCodeSimdReg));
+ SetA64("0x00111000100000000110xxxxxxxxxx", AInstEmit.Rev16_V, typeof(AOpCodeSimd));
+ SetA64("0x1011100x100000000010xxxxxxxxxx", AInstEmit.Rev32_V, typeof(AOpCodeSimd));
SetA64("0x001110<<100000000010xxxxxxxxxx", AInstEmit.Rev64_V, typeof(AOpCodeSimd));
SetA64("0x101110<<1xxxxx011000xxxxxxxxxx", AInstEmit.Rsubhn_V, typeof(AOpCodeSimdReg));
SetA64("0x001110<<1xxxxx000100xxxxxxxxxx", AInstEmit.Saddw_V, typeof(AOpCodeSimdReg));
diff --git a/ChocolArm64/Instruction/AInstEmitSimdLogical.cs b/ChocolArm64/Instruction/AInstEmitSimdLogical.cs
index cb6ee4cd..163151f8 100644
--- a/ChocolArm64/Instruction/AInstEmitSimdLogical.cs
+++ b/ChocolArm64/Instruction/AInstEmitSimdLogical.cs
@@ -1,6 +1,7 @@
using ChocolArm64.Decoder;
using ChocolArm64.State;
using ChocolArm64.Translation;
+using System;
using System.Reflection.Emit;
using System.Runtime.Intrinsics.X86;
@@ -144,23 +145,48 @@ namespace ChocolArm64.Instruction
EmitVectorImmBinaryOp(Context, () => 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;
int Bytes = Context.CurrOp.GetBitsCount() >> 3;
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);