Add tests and fix issues with VTRN, VZIP, VUZP
This commit is contained in:
parent
491154c7bb
commit
301ced766c
4 changed files with 110 additions and 4 deletions
|
@ -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);
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue