Add tests and fix issues with VTRN, VZIP, VUZP

This commit is contained in:
riperiperi 2020-01-13 17:47:22 +00:00
commit 301ced766c
4 changed files with 110 additions and 4 deletions

View file

@ -242,7 +242,7 @@ namespace ARMeilleure.Instructions
me = ExtractScalar(context, type, op.Vm);
}
Delegate dlg = op.Size != 0
Delegate dlg = fSize != 0
? (Delegate)new _S32_F64_F64_Bool(SoftFloat64.FPCompare)
: (Delegate)new _S32_F32_F32_Bool(SoftFloat32.FPCompare);

View file

@ -114,6 +114,8 @@ namespace ARMeilleure.Instructions
OperandType type = (op.Size & 1) != 0 ? OperandType.I64 : OperandType.I32;
if (op.Size < 2) throw new Exception("Not supported right now");
Operand n = ExtractScalar(context, type, op.Vn);
Operand m = ExtractScalar(context, type, op.Vm);

View file

@ -115,6 +115,8 @@ namespace ARMeilleure.Instructions
(int vm, int em) = GetQuadwordAndSubindex(op.Vm, op.RegisterSize);
(int vd, int ed) = GetQuadwordAndSubindex(op.Vd, op.RegisterSize);
bool overlap = vm == vd;
Operand resD = GetVecA32(vd);
Operand resM = GetVecA32(vm);
@ -125,11 +127,13 @@ namespace ARMeilleure.Instructions
Operand m1 = EmitVectorExtract32(context, vm, pairIndex + em * elems, op.Size, false);
resD = EmitVectorInsert(context, resD, m1, pairIndex + 1 + ed * elems, op.Size);
if (overlap) resM = resD;
resM = EmitVectorInsert(context, resM, d2, pairIndex + em * elems, op.Size);
if (overlap) resD = resM;
}
context.Copy(GetVecA32(vd), resD);
context.Copy(GetVecA32(vm), resM);
if (!overlap) context.Copy(GetVecA32(vm), resM);
}
public static void Vzip(ArmEmitterContext context)
@ -142,6 +146,8 @@ namespace ARMeilleure.Instructions
(int vm, int em) = GetQuadwordAndSubindex(op.Vm, op.RegisterSize);
(int vd, int ed) = GetQuadwordAndSubindex(op.Vd, op.RegisterSize);
bool overlap = vm == vd;
Operand resD = GetVecA32(vd);
Operand resM = GetVecA32(vm);
@ -157,12 +163,16 @@ namespace ARMeilleure.Instructions
resD = EmitVectorInsert(context, resD, dRowD, pairIndex + ed * elems, op.Size);
resD = EmitVectorInsert(context, resD, mRowD, pairIndex + 1 + ed * elems, op.Size);
if (overlap) resM = resD;
resM = EmitVectorInsert(context, resM, dRowM, pairIndex + em * elems, op.Size);
resM = EmitVectorInsert(context, resM, mRowM, pairIndex + 1 + em * elems, op.Size);
if (overlap) resD = resM;
}
context.Copy(GetVecA32(vd), resD);
context.Copy(GetVecA32(vm), resM);
if (!overlap) context.Copy(GetVecA32(vm), resM);
}
public static void Vuzp(ArmEmitterContext context)
@ -175,6 +185,8 @@ namespace ARMeilleure.Instructions
(int vm, int em) = GetQuadwordAndSubindex(op.Vm, op.RegisterSize);
(int vd, int ed) = GetQuadwordAndSubindex(op.Vd, op.RegisterSize);
bool overlap = vm == vd;
Operand resD = GetVecA32(vd);
Operand resM = GetVecA32(vm);
@ -194,11 +206,13 @@ namespace ARMeilleure.Instructions
}
resD = EmitVectorInsert(context, resD, dIns, index + ed * elems, op.Size);
if (overlap) resM = resD;
resM = EmitVectorInsert(context, resM, mIns, index + em * elems, op.Size);
if (overlap) resD = resM;
}
context.Copy(GetVecA32(vd), resD);
context.Copy(GetVecA32(vm), resM);
if (!overlap) context.Copy(GetVecA32(vm), resM);
}
}
}

View file

@ -103,6 +103,96 @@ namespace Ryujinx.Tests.Cpu
CompareAgainstUnicorn();
}
[Test, Combinatorial, Description("VTRN.<size> <Vd>, <Vm>")]
public void Vtrn([Values(0u, 1u, 2u, 3u)] uint vm,
[Values(0u, 1u, 2u, 3u)] uint vd,
[Values(0u, 1u, 2u)] uint size,
[Values] bool q)
{
uint opcode = 0xf3b20080;
if (vm == vd) return; //undefined
if (q)
{
opcode |= 1 << 6;
vd <<= 1; vm <<= 1;
}
opcode |= (vm & 0x10) << 1;
opcode |= (vm & 0xf);
opcode |= (vd & 0x10) << 18;
opcode |= (vd & 0xf) << 12;
opcode |= (size & 0x3) << 18;
V128 v0 = new V128(TestContext.CurrentContext.Random.NextULong(), TestContext.CurrentContext.Random.NextULong());
V128 v1 = new V128(TestContext.CurrentContext.Random.NextULong(), TestContext.CurrentContext.Random.NextULong());
V128 v2 = new V128(TestContext.CurrentContext.Random.NextULong(), TestContext.CurrentContext.Random.NextULong());
V128 v3 = new V128(TestContext.CurrentContext.Random.NextULong(), TestContext.CurrentContext.Random.NextULong());
SingleOpcode(opcode, v0: v0, v1: v1, v2: v2, v3: v3); //correct
CompareAgainstUnicorn();
}
[Test, Combinatorial, Description("VZIP.<size> <Vd>, <Vm>")]
public void Vzip([Values(0u, 1u, 2u, 3u)] uint vm,
[Values(0u, 1u, 2u, 3u)] uint vd,
[Values(0u, 1u, 2u)] uint size,
[Values] bool q)
{
uint opcode = 0xf3b20180;
if (vm == vd || (size == 2 && !q)) return; //undefined
if (q)
{
opcode |= 1 << 6;
vd <<= 1; vm <<= 1;
}
opcode |= (vm & 0x10) << 1;
opcode |= (vm & 0xf);
opcode |= (vd & 0x10) << 18;
opcode |= (vd & 0xf) << 12;
opcode |= (size & 0x3) << 18;
V128 v0 = new V128(TestContext.CurrentContext.Random.NextULong(), TestContext.CurrentContext.Random.NextULong());
V128 v1 = new V128(TestContext.CurrentContext.Random.NextULong(), TestContext.CurrentContext.Random.NextULong());
V128 v2 = new V128(TestContext.CurrentContext.Random.NextULong(), TestContext.CurrentContext.Random.NextULong());
V128 v3 = new V128(TestContext.CurrentContext.Random.NextULong(), TestContext.CurrentContext.Random.NextULong());
SingleOpcode(opcode, v0: v0, v1: v1, v2: v2, v3: v3); //correct
CompareAgainstUnicorn();
}
[Test, Combinatorial, Description("VUZP.<size> <Vd>, <Vm>")]
public void Vuzp([Values(0u, 1u, 2u, 3u)] uint vm,
[Values(0u, 1u, 2u, 3u)] uint vd,
[Values(0u, 1u, 2u)] uint size,
[Values] bool q)
{
uint opcode = 0xf3b20100;
if (vm == vd || (size == 2 && !q)) return; //undefined
if (q)
{
opcode |= 1 << 6;
vd <<= 1; vm <<= 1;
}
opcode |= (vm & 0x10) << 1;
opcode |= (vm & 0xf);
opcode |= (vd & 0x10) << 18;
opcode |= (vd & 0xf) << 12;
opcode |= (size & 0x3) << 18;
V128 v0 = new V128(TestContext.CurrentContext.Random.NextULong(), TestContext.CurrentContext.Random.NextULong());
V128 v1 = new V128(TestContext.CurrentContext.Random.NextULong(), TestContext.CurrentContext.Random.NextULong());
V128 v2 = new V128(TestContext.CurrentContext.Random.NextULong(), TestContext.CurrentContext.Random.NextULong());
V128 v3 = new V128(TestContext.CurrentContext.Random.NextULong(), TestContext.CurrentContext.Random.NextULong());
SingleOpcode(opcode, v0: v0, v1: v1, v2: v2, v3: v3); //correct
CompareAgainstUnicorn();
}
#endif
}
}