aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorgdkchan <gab.dark.100@gmail.com>2019-02-23 20:52:48 -0300
committerGitHub <noreply@github.com>2019-02-23 20:52:48 -0300
commit9679896b9471afdebf860c016d3fd360b9af7f80 (patch)
tree8b122155dbe528db1aa9237be185f0ddf6fefbaf
parent7ed2b4cc39ca286a03589cd3768a419c5ed9941f (diff)
Implement fixed-point variant of the UCVTF and SCVTF instructions (#578)
* Add fixed-point variant of the UCVTF instruction * Change encoding of some fixed-point instructions to not allow invalid encodings * Fix Fcvtzu_Gp_Fixed encoding * Add SCVTF (fixed-point GP to Scalar) instruction * Simplify *Fixed encodings
-rw-r--r--ChocolArm64/Decoders/OpCodeSimdCvt64.cs9
-rw-r--r--ChocolArm64/Instructions/InstEmitSimdCvt.cs108
-rw-r--r--ChocolArm64/OpCodeTable.cs6
3 files changed, 76 insertions, 47 deletions
diff --git a/ChocolArm64/Decoders/OpCodeSimdCvt64.cs b/ChocolArm64/Decoders/OpCodeSimdCvt64.cs
index eacd5940..3181a85a 100644
--- a/ChocolArm64/Decoders/OpCodeSimdCvt64.cs
+++ b/ChocolArm64/Decoders/OpCodeSimdCvt64.cs
@@ -8,18 +8,9 @@ namespace ChocolArm64.Decoders
public OpCodeSimdCvt64(Inst inst, long position, int opCode) : base(inst, position, opCode)
{
- //TODO:
- //Und of Fixed Point variants.
int scale = (opCode >> 10) & 0x3f;
int sf = (opCode >> 31) & 0x1;
- /*if (Type != SF && !(Type == 2 && SF == 1))
- {
- Emitter = AInstEmit.Und;
-
- return;
- }*/
-
FBits = 64 - scale;
RegisterSize = sf != 0
diff --git a/ChocolArm64/Instructions/InstEmitSimdCvt.cs b/ChocolArm64/Instructions/InstEmitSimdCvt.cs
index 2eac3194..11105d89 100644
--- a/ChocolArm64/Instructions/InstEmitSimdCvt.cs
+++ b/ChocolArm64/Instructions/InstEmitSimdCvt.cs
@@ -244,7 +244,7 @@ namespace ChocolArm64.Instructions
public static void Fcvtzs_Gp_Fixed(ILEmitterCtx context)
{
- EmitFcvtzs_Gp_Fix(context);
+ EmitFcvtzs_Gp_Fixed(context);
}
public static void Fcvtzs_S(ILEmitterCtx context)
@@ -264,7 +264,7 @@ namespace ChocolArm64.Instructions
public static void Fcvtzu_Gp_Fixed(ILEmitterCtx context)
{
- EmitFcvtzu_Gp_Fix(context);
+ EmitFcvtzu_Gp_Fixed(context);
}
public static void Fcvtzu_S(ILEmitterCtx context)
@@ -293,6 +293,24 @@ namespace ChocolArm64.Instructions
EmitScalarSetF(context, op.Rd, op.Size);
}
+ public static void Scvtf_Gp_Fixed(ILEmitterCtx context)
+ {
+ OpCodeSimdCvt64 op = (OpCodeSimdCvt64)context.CurrOp;
+
+ context.EmitLdintzr(op.Rn);
+
+ if (context.CurrOp.RegisterSize == RegisterSize.Int32)
+ {
+ context.Emit(OpCodes.Conv_I4);
+ }
+
+ EmitFloatCast(context, op.Size);
+
+ EmitI2fFBitsMul(context, op.Size, op.FBits);
+
+ EmitScalarSetF(context, op.Rd, op.Size);
+ }
+
public static void Scvtf_S(ILEmitterCtx context)
{
OpCodeSimd64 op = (OpCodeSimd64)context.CurrOp;
@@ -349,48 +367,42 @@ namespace ChocolArm64.Instructions
EmitScalarSetF(context, op.Rd, op.Size);
}
- public static void Ucvtf_S(ILEmitterCtx context)
+ public static void Ucvtf_Gp_Fixed(ILEmitterCtx context)
{
- OpCodeSimd64 op = (OpCodeSimd64)context.CurrOp;
+ OpCodeSimdCvt64 op = (OpCodeSimdCvt64)context.CurrOp;
- EmitVectorExtractZx(context, op.Rn, 0, op.Size + 2);
+ context.EmitLdintzr(op.Rn);
+
+ if (context.CurrOp.RegisterSize == RegisterSize.Int32)
+ {
+ context.Emit(OpCodes.Conv_U4);
+ }
context.Emit(OpCodes.Conv_R_Un);
EmitFloatCast(context, op.Size);
+ EmitI2fFBitsMul(context, op.Size, op.FBits);
+
EmitScalarSetF(context, op.Rd, op.Size);
}
- public static void Ucvtf_V(ILEmitterCtx context)
+ public static void Ucvtf_S(ILEmitterCtx context)
{
- EmitVectorCvtf(context, signed: false);
- }
+ OpCodeSimd64 op = (OpCodeSimd64)context.CurrOp;
- private static int GetFBits(ILEmitterCtx context)
- {
- if (context.CurrOp is OpCodeSimdShImm64 op)
- {
- return GetImmShr(op);
- }
+ EmitVectorExtractZx(context, op.Rn, 0, op.Size + 2);
- return 0;
+ context.Emit(OpCodes.Conv_R_Un);
+
+ EmitFloatCast(context, op.Size);
+
+ EmitScalarSetF(context, op.Rd, op.Size);
}
- private static void EmitFloatCast(ILEmitterCtx context, int size)
+ public static void Ucvtf_V(ILEmitterCtx context)
{
- if (size == 0)
- {
- context.Emit(OpCodes.Conv_R4);
- }
- else if (size == 1)
- {
- context.Emit(OpCodes.Conv_R8);
- }
- else
- {
- throw new ArgumentOutOfRangeException(nameof(size));
- }
+ EmitVectorCvtf(context, signed: false);
}
private static void EmitFcvtn(ILEmitterCtx context, bool signed, bool scalar)
@@ -476,17 +488,17 @@ namespace ChocolArm64.Instructions
context.EmitStintzr(op.Rd);
}
- private static void EmitFcvtzs_Gp_Fix(ILEmitterCtx context)
+ private static void EmitFcvtzs_Gp_Fixed(ILEmitterCtx context)
{
- EmitFcvtz__Gp_Fix(context, true);
+ EmitFcvtz__Gp_Fixed(context, true);
}
- private static void EmitFcvtzu_Gp_Fix(ILEmitterCtx context)
+ private static void EmitFcvtzu_Gp_Fixed(ILEmitterCtx context)
{
- EmitFcvtz__Gp_Fix(context, false);
+ EmitFcvtz__Gp_Fixed(context, false);
}
- private static void EmitFcvtz__Gp_Fix(ILEmitterCtx context, bool signed)
+ private static void EmitFcvtz__Gp_Fixed(ILEmitterCtx context, bool signed)
{
OpCodeSimdCvt64 op = (OpCodeSimdCvt64)context.CurrOp;
@@ -530,9 +542,7 @@ namespace ChocolArm64.Instructions
context.Emit(OpCodes.Conv_R_Un);
}
- context.Emit(sizeF == 0
- ? OpCodes.Conv_R4
- : OpCodes.Conv_R8);
+ EmitFloatCast(context, sizeF);
EmitI2fFBitsMul(context, sizeF, fBits);
@@ -644,6 +654,32 @@ namespace ChocolArm64.Instructions
}
}
+ private static int GetFBits(ILEmitterCtx context)
+ {
+ if (context.CurrOp is OpCodeSimdShImm64 op)
+ {
+ return GetImmShr(op);
+ }
+
+ return 0;
+ }
+
+ private static void EmitFloatCast(ILEmitterCtx context, int size)
+ {
+ if (size == 0)
+ {
+ context.Emit(OpCodes.Conv_R4);
+ }
+ else if (size == 1)
+ {
+ context.Emit(OpCodes.Conv_R8);
+ }
+ else
+ {
+ throw new ArgumentOutOfRangeException(nameof(size));
+ }
+ }
+
private static void EmitScalarFcvts(ILEmitterCtx context, int size, int fBits)
{
if (size < 0 || size > 1)
diff --git a/ChocolArm64/OpCodeTable.cs b/ChocolArm64/OpCodeTable.cs
index 3a8d3948..9fdda87b 100644
--- a/ChocolArm64/OpCodeTable.cs
+++ b/ChocolArm64/OpCodeTable.cs
@@ -310,12 +310,12 @@ namespace ChocolArm64
SetA64("x00111100x101000000000xxxxxxxxxx", InstEmit.Fcvtps_Gp, typeof(OpCodeSimdCvt64));
SetA64("x00111100x101001000000xxxxxxxxxx", InstEmit.Fcvtpu_Gp, typeof(OpCodeSimdCvt64));
SetA64("x00111100x111000000000xxxxxxxxxx", InstEmit.Fcvtzs_Gp, typeof(OpCodeSimdCvt64));
- SetA64("x00111100x011000xxxxxxxxxxxxxxxx", InstEmit.Fcvtzs_Gp_Fixed, typeof(OpCodeSimdCvt64));
+ SetA64(">00111100x011000>xxxxxxxxxxxxxxx", InstEmit.Fcvtzs_Gp_Fixed, typeof(OpCodeSimdCvt64));
SetA64("010111101x100001101110xxxxxxxxxx", InstEmit.Fcvtzs_S, typeof(OpCodeSimd64));
SetA64("0>0011101<100001101110xxxxxxxxxx", InstEmit.Fcvtzs_V, typeof(OpCodeSimd64));
SetA64("0x0011110>>xxxxx111111xxxxxxxxxx", InstEmit.Fcvtzs_V, typeof(OpCodeSimdShImm64));
SetA64("x00111100x111001000000xxxxxxxxxx", InstEmit.Fcvtzu_Gp, typeof(OpCodeSimdCvt64));
- SetA64("x00111100x011001xxxxxxxxxxxxxxxx", InstEmit.Fcvtzu_Gp_Fixed, typeof(OpCodeSimdCvt64));
+ SetA64(">00111100x011001>xxxxxxxxxxxxxxx", InstEmit.Fcvtzu_Gp_Fixed, typeof(OpCodeSimdCvt64));
SetA64("011111101x100001101110xxxxxxxxxx", InstEmit.Fcvtzu_S, typeof(OpCodeSimd64));
SetA64("0>1011101<100001101110xxxxxxxxxx", InstEmit.Fcvtzu_V, typeof(OpCodeSimd64));
SetA64("0x1011110>>xxxxx111111xxxxxxxxxx", InstEmit.Fcvtzu_V, typeof(OpCodeSimdShImm64));
@@ -434,6 +434,7 @@ namespace ChocolArm64
SetA64("0x001110<<100000001010xxxxxxxxxx", InstEmit.Saddlp_V, typeof(OpCodeSimd64));
SetA64("0x001110<<1xxxxx000100xxxxxxxxxx", InstEmit.Saddw_V, typeof(OpCodeSimdReg64));
SetA64("x00111100x100010000000xxxxxxxxxx", InstEmit.Scvtf_Gp, typeof(OpCodeSimdCvt64));
+ SetA64(">00111100x000010>xxxxxxxxxxxxxxx", InstEmit.Scvtf_Gp_Fixed, typeof(OpCodeSimdCvt64));
SetA64("010111100x100001110110xxxxxxxxxx", InstEmit.Scvtf_S, typeof(OpCodeSimd64));
SetA64("0>0011100<100001110110xxxxxxxxxx", InstEmit.Scvtf_V, typeof(OpCodeSimd64));
SetA64("01011110000xxxxx000000xxxxxxxxxx", InstEmit.Sha1c_V, typeof(OpCodeSimdReg64));
@@ -542,6 +543,7 @@ namespace ChocolArm64
SetA64("01101110<<110000001110xxxxxxxxxx", InstEmit.Uaddlv_V, typeof(OpCodeSimd64));
SetA64("0x101110<<1xxxxx000100xxxxxxxxxx", InstEmit.Uaddw_V, typeof(OpCodeSimdReg64));
SetA64("x00111100x100011000000xxxxxxxxxx", InstEmit.Ucvtf_Gp, typeof(OpCodeSimdCvt64));
+ SetA64(">00111100x000011>xxxxxxxxxxxxxxx", InstEmit.Ucvtf_Gp_Fixed, typeof(OpCodeSimdCvt64));
SetA64("011111100x100001110110xxxxxxxxxx", InstEmit.Ucvtf_S, typeof(OpCodeSimd64));
SetA64("0>1011100<100001110110xxxxxxxxxx", InstEmit.Ucvtf_V, typeof(OpCodeSimd64));
SetA64("0x101110<<1xxxxx000001xxxxxxxxxx", InstEmit.Uhadd_V, typeof(OpCodeSimdReg64));