aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorgdkchan <gab.dark.100@gmail.com>2018-03-14 00:12:05 -0300
committergdkchan <gab.dark.100@gmail.com>2018-03-14 00:12:05 -0300
commit553ba659c40013cde0198c2bdd10b31bdd6f3d97 (patch)
tree266b13399ec274a61497ae430abd036f9196c1ee
parent19564e570baab98754cb808c704fbd9c924abc60 (diff)
Add CRC32 instruction and SLI (vector)
-rw-r--r--ChocolArm64/AOpCodeTable.cs9
-rw-r--r--ChocolArm64/Instruction/AInstEmitHash.cs74
-rw-r--r--ChocolArm64/Instruction/AInstEmitSimdShift.cs54
-rw-r--r--ChocolArm64/Instruction/ASoftFallback.cs78
4 files changed, 205 insertions, 10 deletions
diff --git a/ChocolArm64/AOpCodeTable.cs b/ChocolArm64/AOpCodeTable.cs
index 60646d0e..d32bd9cd 100644
--- a/ChocolArm64/AOpCodeTable.cs
+++ b/ChocolArm64/AOpCodeTable.cs
@@ -42,6 +42,14 @@ namespace ChocolArm64
Set("x1111010010xxxxxxxxx00xxxxxxxxxx", AInstEmit.Ccmp, typeof(AOpCodeCcmpReg));
Set("11010101000000110011xxxx01011111", AInstEmit.Clrex, typeof(AOpCodeSystem));
Set("x101101011000000000100xxxxxxxxxx", AInstEmit.Clz, typeof(AOpCodeAlu));
+ Set("x0011010110xxxxx010000xxxxxxxxxx", AInstEmit.Crc32b, typeof(AOpCodeAluRs));
+ Set("x0011010110xxxxx010001xxxxxxxxxx", AInstEmit.Crc32h, typeof(AOpCodeAluRs));
+ Set("x0011010110xxxxx010010xxxxxxxxxx", AInstEmit.Crc32w, typeof(AOpCodeAluRs));
+ Set("x0011010110xxxxx010011xxxxxxxxxx", AInstEmit.Crc32x, typeof(AOpCodeAluRs));
+ Set("x0011010110xxxxx010100xxxxxxxxxx", AInstEmit.Crc32cb, typeof(AOpCodeAluRs));
+ Set("x0011010110xxxxx010101xxxxxxxxxx", AInstEmit.Crc32ch, typeof(AOpCodeAluRs));
+ Set("x0011010110xxxxx010110xxxxxxxxxx", AInstEmit.Crc32cw, typeof(AOpCodeAluRs));
+ Set("x0011010110xxxxx010111xxxxxxxxxx", AInstEmit.Crc32cx, typeof(AOpCodeAluRs));
Set("x0011010100xxxxxxxxx00xxxxxxxxxx", AInstEmit.Csel, typeof(AOpCodeCsel));
Set("x0011010100xxxxxxxxx01xxxxxxxxxx", AInstEmit.Csinc, typeof(AOpCodeCsel));
Set("x1011010100xxxxxxxxx00xxxxxxxxxx", AInstEmit.Csinv, typeof(AOpCodeCsel));
@@ -243,6 +251,7 @@ namespace ChocolArm64
Set("0x0011110>>>>xxx010101xxxxxxxxxx", AInstEmit.Shl_V, typeof(AOpCodeSimdShImm));
Set("0x101110<<100001001110xxxxxxxxxx", AInstEmit.Shll_V, typeof(AOpCodeSimd));
Set("0x00111100>>>xxx100001xxxxxxxxxx", AInstEmit.Shrn_V, typeof(AOpCodeSimdShImm));
+ Set("0x1011110>>>>xxx010101xxxxxxxxxx", AInstEmit.Sli_V, typeof(AOpCodeSimdShImm));
Set("0x001110<<1xxxxx011001xxxxxxxxxx", AInstEmit.Smax_V, typeof(AOpCodeSimdReg));
Set("0x001110<<1xxxxx011011xxxxxxxxxx", AInstEmit.Smin_V, typeof(AOpCodeSimdReg));
Set("0x001110<<1xxxxx100000xxxxxxxxxx", AInstEmit.Smlal_V, typeof(AOpCodeSimdReg));
diff --git a/ChocolArm64/Instruction/AInstEmitHash.cs b/ChocolArm64/Instruction/AInstEmitHash.cs
new file mode 100644
index 00000000..fd98f563
--- /dev/null
+++ b/ChocolArm64/Instruction/AInstEmitHash.cs
@@ -0,0 +1,74 @@
+using ChocolArm64.Decoder;
+using ChocolArm64.State;
+using ChocolArm64.Translation;
+using System.Reflection.Emit;
+
+namespace ChocolArm64.Instruction
+{
+ static partial class AInstEmit
+ {
+
+ public static void Crc32b(AILEmitterCtx Context)
+ {
+ EmitCrc32(Context, nameof(ASoftFallback.Crc32b));
+ }
+
+ public static void Crc32h(AILEmitterCtx Context)
+ {
+ EmitCrc32(Context, nameof(ASoftFallback.Crc32h));
+ }
+
+ public static void Crc32w(AILEmitterCtx Context)
+ {
+ EmitCrc32(Context, nameof(ASoftFallback.Crc32w));
+ }
+
+ public static void Crc32x(AILEmitterCtx Context)
+ {
+ EmitCrc32(Context, nameof(ASoftFallback.Crc32x));
+ }
+
+ public static void Crc32cb(AILEmitterCtx Context)
+ {
+ EmitCrc32(Context, nameof(ASoftFallback.Crc32cb));
+ }
+
+ public static void Crc32ch(AILEmitterCtx Context)
+ {
+ EmitCrc32(Context, nameof(ASoftFallback.Crc32ch));
+ }
+
+ public static void Crc32cw(AILEmitterCtx Context)
+ {
+ EmitCrc32(Context, nameof(ASoftFallback.Crc32cw));
+ }
+
+ public static void Crc32cx(AILEmitterCtx Context)
+ {
+ EmitCrc32(Context, nameof(ASoftFallback.Crc32cx));
+ }
+
+ private static void EmitCrc32(AILEmitterCtx Context, string Name)
+ {
+ AOpCodeAluRs Op = (AOpCodeAluRs)Context.CurrOp;
+
+ Context.EmitLdintzr(Op.Rn);
+
+ if (Op.RegisterSize != ARegisterSize.Int32)
+ {
+ Context.Emit(OpCodes.Conv_U4);
+ }
+
+ Context.EmitLdintzr(Op.Rm);
+
+ ASoftFallback.EmitCall(Context, Name);
+
+ if (Op.RegisterSize != ARegisterSize.Int32)
+ {
+ Context.Emit(OpCodes.Conv_U8);
+ }
+
+ Context.EmitStintzr(Op.Rd);
+ }
+ }
+} \ No newline at end of file
diff --git a/ChocolArm64/Instruction/AInstEmitSimdShift.cs b/ChocolArm64/Instruction/AInstEmitSimdShift.cs
index bb8a8f17..bffed57e 100644
--- a/ChocolArm64/Instruction/AInstEmitSimdShift.cs
+++ b/ChocolArm64/Instruction/AInstEmitSimdShift.cs
@@ -29,7 +29,7 @@ namespace ChocolArm64.Instruction
int Shift = Op.Imm - (8 << Op.Size);
- EmitVectorBinaryShImmBinaryZx(Context, () => Context.Emit(OpCodes.Shl), Shift);
+ EmitVectorShImmBinaryZx(Context, () => Context.Emit(OpCodes.Shl), Shift);
}
public static void Shll_V(AILEmitterCtx Context)
@@ -50,6 +50,40 @@ namespace ChocolArm64.Instruction
EmitVectorShImmNarrowBinaryZx(Context, () => Context.Emit(OpCodes.Shr_Un), Shift);
}
+ public static void Sli_V(AILEmitterCtx Context)
+ {
+ AOpCodeSimdShImm Op = (AOpCodeSimdShImm)Context.CurrOp;
+
+ int Bytes = Context.CurrOp.GetBitsCount() >> 3;
+
+ int Shift = Op.Imm - (8 << Op.Size);
+
+ ulong Mask = ulong.MaxValue >> (64 - Shift);
+
+ for (int Index = 0; Index < (Bytes >> Op.Size); Index++)
+ {
+ EmitVectorExtractZx(Context, Op.Rn, Index, Op.Size);
+
+ Context.EmitLdc_I4(Shift);
+
+ Context.Emit(OpCodes.Shl);
+
+ EmitVectorExtractZx(Context, Op.Rd, Index, Op.Size);
+
+ Context.EmitLdc_I8((long)Mask);
+
+ Context.Emit(OpCodes.And);
+ Context.Emit(OpCodes.Or);
+
+ EmitVectorInsert(Context, Op.Rd, Index, Op.Size);
+ }
+
+ if (Op.RegisterSize == ARegisterSize.SIMD64)
+ {
+ EmitVectorZeroUpper(Context, Op.Rd);
+ }
+ }
+
public static void Sshl_V(AILEmitterCtx Context)
{
EmitVectorShl(Context, Signed: true);
@@ -83,7 +117,7 @@ namespace ChocolArm64.Instruction
int Shift = (8 << (Op.Size + 1)) - Op.Imm;
- EmitVectorBinaryShImmBinarySx(Context, () => Context.Emit(OpCodes.Shr), Shift);
+ EmitVectorShImmBinarySx(Context, () => Context.Emit(OpCodes.Shr), Shift);
}
public static void Ssra_V(AILEmitterCtx Context)
@@ -98,7 +132,7 @@ namespace ChocolArm64.Instruction
Context.Emit(OpCodes.Add);
};
- EmitVectorTernaryShImmBinarySx(Context, Emit, Shift);
+ EmitVectorShImmTernarySx(Context, Emit, Shift);
}
public static void Ushl_V(AILEmitterCtx Context)
@@ -217,22 +251,22 @@ namespace ChocolArm64.Instruction
}
}
- private static void EmitVectorBinaryShImmBinarySx(AILEmitterCtx Context, Action Emit, int Imm)
+ private static void EmitVectorShImmBinarySx(AILEmitterCtx Context, Action Emit, int Imm)
{
- EmitVectorShImmBinaryOp(Context, Emit, Imm, false, true);
+ EmitVectorShImmOp(Context, Emit, Imm, false, true);
}
- private static void EmitVectorTernaryShImmBinarySx(AILEmitterCtx Context, Action Emit, int Imm)
+ private static void EmitVectorShImmTernarySx(AILEmitterCtx Context, Action Emit, int Imm)
{
- EmitVectorShImmBinaryOp(Context, Emit, Imm, true, true);
+ EmitVectorShImmOp(Context, Emit, Imm, true, true);
}
- private static void EmitVectorBinaryShImmBinaryZx(AILEmitterCtx Context, Action Emit, int Imm)
+ private static void EmitVectorShImmBinaryZx(AILEmitterCtx Context, Action Emit, int Imm)
{
- EmitVectorShImmBinaryOp(Context, Emit, Imm, false, false);
+ EmitVectorShImmOp(Context, Emit, Imm, false, false);
}
- private static void EmitVectorShImmBinaryOp(AILEmitterCtx Context, Action Emit, int Imm, bool Ternary, bool Signed)
+ private static void EmitVectorShImmOp(AILEmitterCtx Context, Action Emit, int Imm, bool Ternary, bool Signed)
{
AOpCodeSimd Op = (AOpCodeSimd)Context.CurrOp;
diff --git a/ChocolArm64/Instruction/ASoftFallback.cs b/ChocolArm64/Instruction/ASoftFallback.cs
index 797d8157..7e5b3dba 100644
--- a/ChocolArm64/Instruction/ASoftFallback.cs
+++ b/ChocolArm64/Instruction/ASoftFallback.cs
@@ -38,6 +38,84 @@ namespace ChocolArm64.Instruction
return (ulong)Size;
}
+ private const uint Crc32RevPoly = 0xedb88320;
+ private const uint Crc32cRevPoly = 0x82f63b78;
+
+ public static uint Crc32b(uint Crc, byte Val) => Crc32 (Crc, Crc32RevPoly, Val);
+ public static uint Crc32h(uint Crc, byte Val) => Crc32h(Crc, Crc32RevPoly, Val);
+ public static uint Crc32w(uint Crc, byte Val) => Crc32w(Crc, Crc32RevPoly, Val);
+ public static uint Crc32x(uint Crc, byte Val) => Crc32x(Crc, Crc32RevPoly, Val);
+
+ public static uint Crc32cb(uint Crc, byte Val) => Crc32 (Crc, Crc32cRevPoly, Val);
+ public static uint Crc32ch(uint Crc, byte Val) => Crc32h(Crc, Crc32cRevPoly, Val);
+ public static uint Crc32cw(uint Crc, byte Val) => Crc32w(Crc, Crc32cRevPoly, Val);
+ public static uint Crc32cx(uint Crc, byte Val) => Crc32x(Crc, Crc32cRevPoly, Val);
+
+ private static uint Crc32h(uint Crc, uint Poly, ushort Val)
+ {
+ Crc = Crc32(Crc, Poly, (byte)(Val >> 0));
+ Crc = Crc32(Crc, Poly, (byte)(Val >> 8));
+
+ return Crc;
+ }
+
+ private static uint Crc32w(uint Crc, uint Poly, uint Val)
+ {
+ Crc = Crc32(Crc, Poly, (byte)(Val >> 0));
+ Crc = Crc32(Crc, Poly, (byte)(Val >> 8));
+ Crc = Crc32(Crc, Poly, (byte)(Val >> 16));
+ Crc = Crc32(Crc, Poly, (byte)(Val >> 24));
+
+ return Crc;
+ }
+
+ private static uint Crc32x(uint Crc, uint Poly, ulong Val)
+ {
+ Crc = Crc32(Crc, Poly, (byte)(Val >> 0));
+ Crc = Crc32(Crc, Poly, (byte)(Val >> 8));
+ Crc = Crc32(Crc, Poly, (byte)(Val >> 16));
+ Crc = Crc32(Crc, Poly, (byte)(Val >> 24));
+ Crc = Crc32(Crc, Poly, (byte)(Val >> 32));
+ Crc = Crc32(Crc, Poly, (byte)(Val >> 40));
+ Crc = Crc32(Crc, Poly, (byte)(Val >> 48));
+ Crc = Crc32(Crc, Poly, (byte)(Val >> 56));
+
+ return Crc;
+ }
+
+ private static uint Crc32(uint Crc, uint Poly, byte Val)
+ {
+ Crc ^= Val;
+
+ for (int Bit = 7; Bit >= 0; Bit--)
+ {
+ uint Mask = (uint)(-(int)(Crc & 1));
+
+ Crc = (Crc >> 1) ^ (Poly & Mask);
+ }
+
+ return Crc;
+ }
+
+ public static uint ReverseBits8(uint Value)
+ {
+ Value = ((Value & 0xaa) >> 1) | ((Value & 0x55) << 1);
+ Value = ((Value & 0xcc) >> 2) | ((Value & 0x33) << 2);
+ Value = ((Value & 0xf0) >> 4) | ((Value & 0x0f) << 4);
+
+ return Value;
+ }
+
+ public static uint ReverseBits16(uint Value)
+ {
+ Value = ((Value & 0xaaaa) >> 1) | ((Value & 0x5555) << 1);
+ Value = ((Value & 0xcccc) >> 2) | ((Value & 0x3333) << 2);
+ Value = ((Value & 0xf0f0) >> 4) | ((Value & 0x0f0f) << 4);
+ Value = ((Value & 0xff00) >> 8) | ((Value & 0x00ff) << 8);
+
+ return Value;
+ }
+
public static uint ReverseBits32(uint Value)
{
Value = ((Value & 0xaaaaaaaa) >> 1) | ((Value & 0x55555555) << 1);