mirror of
https://github.com/ryujinx-mirror/ryujinx.git
synced 2024-12-23 12:05:45 +00:00
CPU (A64): Add Scvtf_S_Fixed & Ucvtf_S_Fixed with Tests. (#1492)
This commit is contained in:
parent
4f3ae6f62c
commit
2cb8bd7006
4 changed files with 88 additions and 22 deletions
|
@ -454,6 +454,7 @@ namespace ARMeilleure.Decoders
|
||||||
SetA64("x00111100x100010000000xxxxxxxxxx", InstName.Scvtf_Gp, InstEmit.Scvtf_Gp, typeof(OpCodeSimdCvt));
|
SetA64("x00111100x100010000000xxxxxxxxxx", InstName.Scvtf_Gp, InstEmit.Scvtf_Gp, typeof(OpCodeSimdCvt));
|
||||||
SetA64(">00111100x000010>xxxxxxxxxxxxxxx", InstName.Scvtf_Gp_Fixed, InstEmit.Scvtf_Gp_Fixed, typeof(OpCodeSimdCvt));
|
SetA64(">00111100x000010>xxxxxxxxxxxxxxx", InstName.Scvtf_Gp_Fixed, InstEmit.Scvtf_Gp_Fixed, typeof(OpCodeSimdCvt));
|
||||||
SetA64("010111100x100001110110xxxxxxxxxx", InstName.Scvtf_S, InstEmit.Scvtf_S, typeof(OpCodeSimd));
|
SetA64("010111100x100001110110xxxxxxxxxx", InstName.Scvtf_S, InstEmit.Scvtf_S, typeof(OpCodeSimd));
|
||||||
|
SetA64("010111110>>xxxxx111001xxxxxxxxxx", InstName.Scvtf_S_Fixed, InstEmit.Scvtf_S_Fixed, typeof(OpCodeSimdShImm));
|
||||||
SetA64("0>0011100<100001110110xxxxxxxxxx", InstName.Scvtf_V, InstEmit.Scvtf_V, typeof(OpCodeSimd));
|
SetA64("0>0011100<100001110110xxxxxxxxxx", InstName.Scvtf_V, InstEmit.Scvtf_V, typeof(OpCodeSimd));
|
||||||
SetA64("0x001111001xxxxx111001xxxxxxxxxx", InstName.Scvtf_V_Fixed, InstEmit.Scvtf_V_Fixed, typeof(OpCodeSimdShImm));
|
SetA64("0x001111001xxxxx111001xxxxxxxxxx", InstName.Scvtf_V_Fixed, InstEmit.Scvtf_V_Fixed, typeof(OpCodeSimdShImm));
|
||||||
SetA64("0100111101xxxxxx111001xxxxxxxxxx", InstName.Scvtf_V_Fixed, InstEmit.Scvtf_V_Fixed, typeof(OpCodeSimdShImm));
|
SetA64("0100111101xxxxxx111001xxxxxxxxxx", InstName.Scvtf_V_Fixed, InstEmit.Scvtf_V_Fixed, typeof(OpCodeSimdShImm));
|
||||||
|
@ -576,6 +577,7 @@ namespace ARMeilleure.Decoders
|
||||||
SetA64("x00111100x100011000000xxxxxxxxxx", InstName.Ucvtf_Gp, InstEmit.Ucvtf_Gp, typeof(OpCodeSimdCvt));
|
SetA64("x00111100x100011000000xxxxxxxxxx", InstName.Ucvtf_Gp, InstEmit.Ucvtf_Gp, typeof(OpCodeSimdCvt));
|
||||||
SetA64(">00111100x000011>xxxxxxxxxxxxxxx", InstName.Ucvtf_Gp_Fixed, InstEmit.Ucvtf_Gp_Fixed, typeof(OpCodeSimdCvt));
|
SetA64(">00111100x000011>xxxxxxxxxxxxxxx", InstName.Ucvtf_Gp_Fixed, InstEmit.Ucvtf_Gp_Fixed, typeof(OpCodeSimdCvt));
|
||||||
SetA64("011111100x100001110110xxxxxxxxxx", InstName.Ucvtf_S, InstEmit.Ucvtf_S, typeof(OpCodeSimd));
|
SetA64("011111100x100001110110xxxxxxxxxx", InstName.Ucvtf_S, InstEmit.Ucvtf_S, typeof(OpCodeSimd));
|
||||||
|
SetA64("011111110>>xxxxx111001xxxxxxxxxx", InstName.Ucvtf_S_Fixed, InstEmit.Ucvtf_S_Fixed, typeof(OpCodeSimdShImm));
|
||||||
SetA64("0>1011100<100001110110xxxxxxxxxx", InstName.Ucvtf_V, InstEmit.Ucvtf_V, typeof(OpCodeSimd));
|
SetA64("0>1011100<100001110110xxxxxxxxxx", InstName.Ucvtf_V, InstEmit.Ucvtf_V, typeof(OpCodeSimd));
|
||||||
SetA64("0x101111001xxxxx111001xxxxxxxxxx", InstName.Ucvtf_V_Fixed, InstEmit.Ucvtf_V_Fixed, typeof(OpCodeSimdShImm));
|
SetA64("0x101111001xxxxx111001xxxxxxxxxx", InstName.Ucvtf_V_Fixed, InstEmit.Ucvtf_V_Fixed, typeof(OpCodeSimdShImm));
|
||||||
SetA64("0110111101xxxxxx111001xxxxxxxxxx", InstName.Ucvtf_V_Fixed, InstEmit.Ucvtf_V_Fixed, typeof(OpCodeSimdShImm));
|
SetA64("0110111101xxxxxx111001xxxxxxxxxx", InstName.Ucvtf_V_Fixed, InstEmit.Ucvtf_V_Fixed, typeof(OpCodeSimdShImm));
|
||||||
|
|
|
@ -494,15 +494,19 @@ namespace ARMeilleure.Instructions
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
OpCodeSimd op = (OpCodeSimd)context.CurrOp;
|
EmitCvtf(context, signed: true, scalar: true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
int sizeF = op.Size & 1;
|
public static void Scvtf_S_Fixed(ArmEmitterContext context)
|
||||||
|
{
|
||||||
Operand res = EmitVectorLongExtract(context, op.Rn, 0, sizeF + 2);
|
if (Optimizations.UseSse2)
|
||||||
|
{
|
||||||
res = EmitFPConvert(context, res, op.Size, signed: true);
|
EmitSse2ScvtfOp(context, scalar: true);
|
||||||
|
}
|
||||||
context.Copy(GetVec(op.Rd), context.VectorInsert(context.VectorZero(), res, 0));
|
else
|
||||||
|
{
|
||||||
|
EmitCvtf(context, signed: true, scalar: true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -514,7 +518,7 @@ namespace ARMeilleure.Instructions
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
EmitVectorCvtf(context, signed: true);
|
EmitCvtf(context, signed: true, scalar: false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -526,7 +530,7 @@ namespace ARMeilleure.Instructions
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
EmitVectorCvtf(context, signed: true);
|
EmitCvtf(context, signed: true, scalar: false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -562,15 +566,19 @@ namespace ARMeilleure.Instructions
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
OpCodeSimd op = (OpCodeSimd)context.CurrOp;
|
EmitCvtf(context, signed: false, scalar: true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
int sizeF = op.Size & 1;
|
public static void Ucvtf_S_Fixed(ArmEmitterContext context)
|
||||||
|
{
|
||||||
Operand ne = EmitVectorLongExtract(context, op.Rn, 0, sizeF + 2);
|
if (Optimizations.UseSse2)
|
||||||
|
{
|
||||||
Operand res = EmitFPConvert(context, ne, sizeF, signed: false);
|
EmitSse2UcvtfOp(context, scalar: true);
|
||||||
|
}
|
||||||
context.Copy(GetVec(op.Rd), context.VectorInsert(context.VectorZero(), res, 0));
|
else
|
||||||
|
{
|
||||||
|
EmitCvtf(context, signed: false, scalar: true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -582,7 +590,7 @@ namespace ARMeilleure.Instructions
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
EmitVectorCvtf(context, signed: false);
|
EmitCvtf(context, signed: false, scalar: false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -594,7 +602,7 @@ namespace ARMeilleure.Instructions
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
EmitVectorCvtf(context, signed: false);
|
EmitCvtf(context, signed: false, scalar: false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -742,7 +750,7 @@ namespace ARMeilleure.Instructions
|
||||||
SetIntOrZR(context, op.Rd, res);
|
SetIntOrZR(context, op.Rd, res);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void EmitVectorCvtf(ArmEmitterContext context, bool signed)
|
private static void EmitCvtf(ArmEmitterContext context, bool signed, bool scalar)
|
||||||
{
|
{
|
||||||
OpCodeSimd op = (OpCodeSimd)context.CurrOp;
|
OpCodeSimd op = (OpCodeSimd)context.CurrOp;
|
||||||
|
|
||||||
|
@ -753,7 +761,7 @@ namespace ARMeilleure.Instructions
|
||||||
|
|
||||||
int fBits = GetFBits(context);
|
int fBits = GetFBits(context);
|
||||||
|
|
||||||
int elems = op.GetBytesCount() >> sizeI;
|
int elems = !scalar ? op.GetBytesCount() >> sizeI : 1;
|
||||||
|
|
||||||
for (int index = 0; index < elems; index++)
|
for (int index = 0; index < elems; index++)
|
||||||
{
|
{
|
||||||
|
|
|
@ -315,6 +315,7 @@ namespace ARMeilleure.Instructions
|
||||||
Scvtf_Gp,
|
Scvtf_Gp,
|
||||||
Scvtf_Gp_Fixed,
|
Scvtf_Gp_Fixed,
|
||||||
Scvtf_S,
|
Scvtf_S,
|
||||||
|
Scvtf_S_Fixed,
|
||||||
Scvtf_V,
|
Scvtf_V,
|
||||||
Scvtf_V_Fixed,
|
Scvtf_V_Fixed,
|
||||||
Sha1c_V,
|
Sha1c_V,
|
||||||
|
@ -414,6 +415,7 @@ namespace ARMeilleure.Instructions
|
||||||
Ucvtf_Gp,
|
Ucvtf_Gp,
|
||||||
Ucvtf_Gp_Fixed,
|
Ucvtf_Gp_Fixed,
|
||||||
Ucvtf_S,
|
Ucvtf_S,
|
||||||
|
Ucvtf_S_Fixed,
|
||||||
Ucvtf_V,
|
Ucvtf_V,
|
||||||
Ucvtf_V_Fixed,
|
Ucvtf_V_Fixed,
|
||||||
Uhadd_V,
|
Uhadd_V,
|
||||||
|
|
|
@ -195,6 +195,24 @@ namespace Ryujinx.Tests.Cpu
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static uint[] _SU_Cvt_F_S_Fixed_S_()
|
||||||
|
{
|
||||||
|
return new uint[]
|
||||||
|
{
|
||||||
|
0x5F20E420u, // SCVTF S0, S1, #32
|
||||||
|
0x7F20E420u // UCVTF S0, S1, #32
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
private static uint[] _SU_Cvt_F_S_Fixed_D_()
|
||||||
|
{
|
||||||
|
return new uint[]
|
||||||
|
{
|
||||||
|
0x5F40E420u, // SCVTF D0, D1, #64
|
||||||
|
0x7F40E420u // UCVTF D0, D1, #64
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
private static uint[] _SU_Cvt_F_V_Fixed_2S_4S_()
|
private static uint[] _SU_Cvt_F_V_Fixed_2S_4S_()
|
||||||
{
|
{
|
||||||
return new uint[]
|
return new uint[]
|
||||||
|
@ -523,6 +541,42 @@ namespace Ryujinx.Tests.Cpu
|
||||||
CompareAgainstUnicorn();
|
CompareAgainstUnicorn();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Test, Pairwise] [Explicit]
|
||||||
|
public void SU_Cvt_F_S_Fixed_S([ValueSource("_SU_Cvt_F_S_Fixed_S_")] uint opcodes,
|
||||||
|
[ValueSource("_1S_")] [Random(RndCnt)] ulong a,
|
||||||
|
[Values(1u, 32u)] [Random(2u, 31u, RndCntFBits)] uint fBits)
|
||||||
|
{
|
||||||
|
uint immHb = (64 - fBits) & 0x7F;
|
||||||
|
|
||||||
|
opcodes |= (immHb << 16);
|
||||||
|
|
||||||
|
ulong z = TestContext.CurrentContext.Random.NextULong();
|
||||||
|
V128 v0 = MakeVectorE0E1(z, z);
|
||||||
|
V128 v1 = MakeVectorE0(a);
|
||||||
|
|
||||||
|
SingleOpcode(opcodes, v0: v0, v1: v1);
|
||||||
|
|
||||||
|
CompareAgainstUnicorn();
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test, Pairwise] [Explicit]
|
||||||
|
public void SU_Cvt_F_S_Fixed_D([ValueSource("_SU_Cvt_F_S_Fixed_D_")] uint opcodes,
|
||||||
|
[ValueSource("_1D_")] [Random(RndCnt)] ulong a,
|
||||||
|
[Values(1u, 64u)] [Random(2u, 63u, RndCntFBits)] uint fBits)
|
||||||
|
{
|
||||||
|
uint immHb = (128 - fBits) & 0x7F;
|
||||||
|
|
||||||
|
opcodes |= (immHb << 16);
|
||||||
|
|
||||||
|
ulong z = TestContext.CurrentContext.Random.NextULong();
|
||||||
|
V128 v0 = MakeVectorE1(z);
|
||||||
|
V128 v1 = MakeVectorE0(a);
|
||||||
|
|
||||||
|
SingleOpcode(opcodes, v0: v0, v1: v1);
|
||||||
|
|
||||||
|
CompareAgainstUnicorn();
|
||||||
|
}
|
||||||
|
|
||||||
[Test, Pairwise] [Explicit]
|
[Test, Pairwise] [Explicit]
|
||||||
public void SU_Cvt_F_V_Fixed_2S_4S([ValueSource("_SU_Cvt_F_V_Fixed_2S_4S_")] uint opcodes,
|
public void SU_Cvt_F_V_Fixed_2S_4S([ValueSource("_SU_Cvt_F_V_Fixed_2S_4S_")] uint opcodes,
|
||||||
[Values(0u)] uint rd,
|
[Values(0u)] uint rd,
|
||||||
|
|
Loading…
Reference in a new issue