diff options
| author | LDj3SNuD <35856442+LDj3SNuD@users.noreply.github.com> | 2019-05-31 00:51:39 +0200 |
|---|---|---|
| committer | gdkchan <gab.dark.100@gmail.com> | 2019-05-30 19:51:39 -0300 |
| commit | ffbfbb554965651194a58ca92a3a5db195cdc7ed (patch) | |
| tree | c5fffc0a958daf9499feb4de3a42bae5467134ce /ChocolArm64/Instructions | |
| parent | e7be60b6c6dab16ad954b00122190e03778b8e70 (diff) | |
Add FCVT <Hd>, <Sn> and FCVT <Sd>, <Hn> Inst.; add Tests. (#692)
* Update OpCodeTable.cs
* Update InstEmitSimdCvt.cs
* Update CpuTestSimd.cs
* Address PR feedback.
Diffstat (limited to 'ChocolArm64/Instructions')
| -rw-r--r-- | ChocolArm64/Instructions/InstEmitSimdCvt.cs | 68 |
1 files changed, 53 insertions, 15 deletions
diff --git a/ChocolArm64/Instructions/InstEmitSimdCvt.cs b/ChocolArm64/Instructions/InstEmitSimdCvt.cs index b34687e1..2b3deb98 100644 --- a/ChocolArm64/Instructions/InstEmitSimdCvt.cs +++ b/ChocolArm64/Instructions/InstEmitSimdCvt.cs @@ -16,45 +16,83 @@ namespace ChocolArm64.Instructions { OpCodeSimd64 op = (OpCodeSimd64)context.CurrOp; - if (Optimizations.UseSse2) + if (op.Size == 0 && op.Opc == 1) // Single -> Double. { - if (op.Size == 1 && op.Opc == 0) + if (Optimizations.UseSse2) { - //Double -> Single. - Type[] typesCvt = new Type[] { typeof(Vector128<float>), typeof(Vector128<double>) }; + Type[] typesCvt = new Type[] { typeof(Vector128<double>), typeof(Vector128<float>) }; VectorHelper.EmitCall(context, nameof(VectorHelper.VectorSingleZero)); context.EmitLdvec(op.Rn); - context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.ConvertScalarToVector128Single), typesCvt)); + context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.ConvertScalarToVector128Double), typesCvt)); context.EmitStvec(op.Rd); } - else if (op.Size == 0 && op.Opc == 1) + else { - //Single -> Double. - Type[] typesCvt = new Type[] { typeof(Vector128<double>), typeof(Vector128<float>) }; + EmitVectorExtractF(context, op.Rn, 0, 0); + + EmitFloatCast(context, 1); + + EmitScalarSetF(context, op.Rd, 1); + } + } + else if (op.Size == 1 && op.Opc == 0) // Double -> Single. + { + if (Optimizations.UseSse2) + { + Type[] typesCvt = new Type[] { typeof(Vector128<float>), typeof(Vector128<double>) }; VectorHelper.EmitCall(context, nameof(VectorHelper.VectorSingleZero)); context.EmitLdvec(op.Rn); - context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.ConvertScalarToVector128Double), typesCvt)); + context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.ConvertScalarToVector128Single), typesCvt)); context.EmitStvec(op.Rd); } else { - //Invalid encoding. - throw new InvalidOperationException(); + EmitVectorExtractF(context, op.Rn, 0, 1); + + EmitFloatCast(context, 0); + + EmitScalarSetF(context, op.Rd, 0); } } - else + else if (op.Size == 0 && op.Opc == 3) // Single -> Half. + { + EmitVectorExtractF(context, op.Rn, 0, 0); + + context.EmitLdarg(TranslatedSub.StateArgIdx); + + context.EmitCall(typeof(SoftFloat32_16), nameof(SoftFloat32_16.FPConvert)); + + context.Emit(OpCodes.Conv_U8); + EmitScalarSet(context, op.Rd, 1); + } + else if (op.Size == 3 && op.Opc == 0) // Half -> Single. { - EmitVectorExtractF(context, op.Rn, 0, op.Size); + EmitVectorExtractZx(context, op.Rn, 0, 1); + context.Emit(OpCodes.Conv_U2); - EmitFloatCast(context, op.Opc); + context.EmitLdarg(TranslatedSub.StateArgIdx); - EmitScalarSetF(context, op.Rd, op.Opc); + context.EmitCall(typeof(SoftFloat16_32), nameof(SoftFloat16_32.FPConvert)); + + EmitScalarSetF(context, op.Rd, 0); + } + else if (op.Size == 1 && op.Opc == 3) // Double -> Half. + { + throw new NotImplementedException("Double-precision to half-precision."); + } + else if (op.Size == 3 && op.Opc == 1) // Double -> Half. + { + throw new NotImplementedException("Half-precision to double-precision."); + } + else // Invalid encoding. + { + throw new InvalidOperationException($"type == {op.Size} && opc == {op.Opc}"); } } |
