aboutsummaryrefslogtreecommitdiff
path: root/ChocolArm64/Instructions/InstEmitSimdMove.cs
diff options
context:
space:
mode:
authorLDj3SNuD <35856442+LDj3SNuD@users.noreply.github.com>2018-12-26 18:11:36 +0100
committergdkchan <gab.dark.100@gmail.com>2018-12-26 15:11:36 -0200
commit0f5b6dfbe8d4bcc4df3f670e366a967d8ea103db (patch)
tree89fe781d39e9e02534fd455a26008db8a3a14341 /ChocolArm64/Instructions/InstEmitSimdMove.cs
parentd8f2497f155046402cd15c65eca0326faf3aefd6 (diff)
Fix Frecpe_S/V and Frsqrte_S/V (full FP emu.). Add Sse Opt. & SoftFloat Impl. for Fcmeq/ge/gt/le/lt_S/V (Reg & Zero), Faddp_S/V, Fmaxp_V, Fminp_V Inst.; add Sse Opt. for Shll_V, S/Ushll_V Inst.; improve Sse Opt. for Xtn_V Inst.. Add Tests. (#543)
* Update Optimizations.cs * Update InstEmitSimdShift.cs * Update InstEmitSimdHelper.cs * Update InstEmitSimdArithmetic.cs * Update InstEmitSimdMove.cs * Update SoftFloat.cs * Update InstEmitSimdCmp.cs * Update CpuTestSimdShImm.cs * Update CpuTestSimd.cs * Update CpuTestSimdReg.cs * Nit. * Update SoftFloat.cs * Update InstEmitSimdArithmetic.cs * Update InstEmitSimdHelper.cs * Update CpuTestSimd.cs * Explicit some implicit casts. * Simplify some powers; nits. * Update OpCodeTable.cs * Update InstEmitSimdArithmetic.cs * Update CpuTestSimdReg.cs * Update InstEmitSimdArithmetic.cs
Diffstat (limited to 'ChocolArm64/Instructions/InstEmitSimdMove.cs')
-rw-r--r--ChocolArm64/Instructions/InstEmitSimdMove.cs80
1 files changed, 26 insertions, 54 deletions
diff --git a/ChocolArm64/Instructions/InstEmitSimdMove.cs b/ChocolArm64/Instructions/InstEmitSimdMove.cs
index 0d9aa312..d40ccff9 100644
--- a/ChocolArm64/Instructions/InstEmitSimdMove.cs
+++ b/ChocolArm64/Instructions/InstEmitSimdMove.cs
@@ -377,75 +377,47 @@ namespace ChocolArm64.Instructions
{
OpCodeSimd64 op = (OpCodeSimd64)context.CurrOp;
- int elems = 8 >> op.Size;
-
- int part = op.RegisterSize == RegisterSize.Simd128 ? elems : 0;
-
- if (Optimizations.UseSse41 && op.Size < 2)
+ if (Optimizations.UseSsse3)
{
- void EmitZeroVector()
- {
- switch (op.Size)
- {
- case 0: VectorHelper.EmitCall(context, nameof(VectorHelper.VectorInt16Zero)); break;
- case 1: VectorHelper.EmitCall(context, nameof(VectorHelper.VectorInt32Zero)); break;
- }
- }
-
- //For XTN, first operand is source, second operand is 0.
- //For XTN2, first operand is 0, second operand is source.
- if (part != 0)
+ long[] masks = new long[]
{
- EmitZeroVector();
- }
-
- EmitLdvecWithSignedCast(context, op.Rn, op.Size + 1);
-
- //Set mask to discard the upper half of the wide elements.
- switch (op.Size)
- {
- case 0: context.EmitLdc_I4(0x00ff); break;
- case 1: context.EmitLdc_I4(0x0000ffff); break;
- }
-
- Type wideType = IntTypesPerSizeLog2[op.Size + 1];
+ 14L << 56 | 12L << 48 | 10L << 40 | 08L << 32 | 06L << 24 | 04L << 16 | 02L << 8 | 00L << 0,
+ 13L << 56 | 12L << 48 | 09L << 40 | 08L << 32 | 05L << 24 | 04L << 16 | 01L << 8 | 00L << 0,
+ 11L << 56 | 10L << 48 | 09L << 40 | 08L << 32 | 03L << 24 | 02L << 16 | 01L << 8 | 00L << 0
+ };
- context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.SetAllVector128), new Type[] { wideType }));
+ Type[] typesMov = new Type[] { typeof(Vector128<float>), typeof(Vector128<float>) };
+ Type[] typesSfl = new Type[] { typeof(Vector128<sbyte>), typeof(Vector128<sbyte>) };
+ Type[] typesSve = new Type[] { typeof(long), typeof(long) };
- wideType = VectorIntTypesPerSizeLog2[op.Size + 1];
+ string nameMov = op.RegisterSize == RegisterSize.Simd128
+ ? nameof(Sse.MoveLowToHigh)
+ : nameof(Sse.MoveHighToLow);
- Type[] wideTypes = new Type[] { wideType, wideType };
+ context.EmitLdvec(op.Rd);
+ VectorHelper.EmitCall(context, nameof(VectorHelper.VectorSingleZero));
- context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.And), wideTypes));
+ context.EmitCall(typeof(Sse).GetMethod(nameof(Sse.MoveLowToHigh), typesMov));
- if (part == 0)
- {
- EmitZeroVector();
- }
+ EmitLdvecWithSignedCast(context, op.Rn, 0);
- //Pack values with signed saturation, the signed saturation shouldn't
- //saturate anything since the upper bits were masked off.
- Type sseType = op.Size == 0 ? typeof(Sse2) : typeof(Sse41);
-
- context.EmitCall(sseType.GetMethod(nameof(Sse2.PackUnsignedSaturate), wideTypes));
-
- if (part != 0)
- {
- //For XTN2, we additionally need to discard the upper bits
- //of the target register and OR the result with it.
- EmitVectorZeroUpper(context, op.Rd);
+ context.EmitLdc_I8(masks[op.Size]);
+ context.Emit(OpCodes.Dup);
- EmitLdvecWithUnsignedCast(context, op.Rd, op.Size);
+ context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.SetVector128), typesSve));
- Type narrowType = VectorUIntTypesPerSizeLog2[op.Size];
+ context.EmitCall(typeof(Ssse3).GetMethod(nameof(Ssse3.Shuffle), typesSfl));
- context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.Or), new Type[] { narrowType, narrowType }));
- }
+ context.EmitCall(typeof(Sse).GetMethod(nameMov, typesMov));
- EmitStvecWithUnsignedCast(context, op.Rd, op.Size);
+ context.EmitStvec(op.Rd);
}
else
{
+ int elems = 8 >> op.Size;
+
+ int part = op.RegisterSize == RegisterSize.Simd128 ? elems : 0;
+
if (part != 0)
{
context.EmitLdvec(op.Rd);