Add Umaal & Vabd_I, Vabdl_I, Vaddl_I, Vhadd, Vqshrn, Vshll inst.s (slow paths). (#1577)

* Add Umaal & Vabd_I, Vabdl_I, Vaddl_I, Vhadd, Vqshrn, Vshll inst.s (slow paths).

No test provided (i.e. draft).

* Ptc InternalVersion = 1577
This commit is contained in:
LDj3SNuD 2020-10-13 22:41:33 +02:00 committed by GitHub
parent 329ba5b39b
commit 04e330cc00
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 171 additions and 15 deletions

View File

@ -8,7 +8,14 @@
{
Q = false;
RegisterSize = RegisterSize.Simd64;
Polynomial = ((opCode >> 9) & 0x1) != 0;
// Subclasses have their own handling of Vx to account for before checking.
if (GetType() == typeof(OpCode32SimdRegLong) && DecoderHelper.VectorArgumentsInvalid(true, Vd))
{
Instruction = InstDescriptor.Undefined;
}
}
}
}

View File

@ -1,6 +1,6 @@
namespace ARMeilleure.Decoders
{
sealed class OpCode32SimdRegWide : OpCode32SimdReg
class OpCode32SimdRegWide : OpCode32SimdReg
{
public OpCode32SimdRegWide(InstDescriptor inst, ulong address, int opCode) : base(inst, address, opCode)
{

View File

@ -2,34 +2,33 @@
{
class OpCode32SimdShImm : OpCode32Simd
{
public int Immediate { get; private set; }
public int Shift { get; private set; }
public OpCode32SimdShImm(InstDescriptor inst, ulong address, int opCode) : base(inst, address, opCode)
{
Immediate = (opCode >> 16) & 0x3f;
var limm = ((opCode >> 1) & 0x40) | Immediate;
int imm6 = (opCode >> 16) & 0x3f;
int limm6 = ((opCode >> 1) & 0x40) | imm6;
if ((limm & 0x40) == 0b1000000)
if ((limm6 & 0x40) == 0b1000000)
{
Size = 3;
Shift = Immediate;
}
else if ((limm & 0x60) == 0b0100000)
Shift = imm6;
}
else if ((limm6 & 0x60) == 0b0100000)
{
Size = 2;
Shift = Immediate - 32;
Shift = imm6 - 32;
}
else if ((limm & 0x70) == 0b0010000)
else if ((limm6 & 0x70) == 0b0010000)
{
Size = 1;
Shift = Immediate - 16;
Shift = imm6 - 16;
}
else if ((limm & 0x78) == 0b0001000)
else if ((limm6 & 0x78) == 0b0001000)
{
Size = 0;
Shift = Immediate - 8;
}
Shift = imm6 - 8;
}
else
{
Instruction = InstDescriptor.Undefined;

View File

@ -0,0 +1,40 @@
namespace ARMeilleure.Decoders
{
class OpCode32SimdShImmLong : OpCode32Simd
{
public int Shift { get; private set; }
public OpCode32SimdShImmLong(InstDescriptor inst, ulong address, int opCode) : base(inst, address, opCode)
{
Q = false;
RegisterSize = RegisterSize.Simd64;
int imm6 = (opCode >> 16) & 0x3f;
if ((imm6 & 0x20) == 0b100000)
{
Size = 2;
Shift = imm6 - 32;
}
else if ((imm6 & 0x30) == 0b010000)
{
Size = 1;
Shift = imm6 - 16;
}
else if ((imm6 & 0x38) == 0b001000)
{
Size = 0;
Shift = imm6 - 8;
}
else
{
Instruction = InstDescriptor.Undefined;
}
if (GetType() == typeof(OpCode32SimdShImmLong) && DecoderHelper.VectorArgumentsInvalid(true, Vd))
{
Instruction = InstDescriptor.Undefined;
}
}
}
}

View File

@ -787,6 +787,7 @@ namespace ARMeilleure.Decoders
SetA32("<<<<00010001xxxx0000xxxx0xx1xxxx", InstName.Tst, InstEmit32.Tst, typeof(OpCode32AluRsReg));
SetA32("<<<<0111111xxxxxxxxxxxxxx101xxxx", InstName.Ubfx, InstEmit32.Ubfx, typeof(OpCode32AluBf));
SetA32("<<<<01110011xxxx1111xxxx0001xxxx", InstName.Udiv, InstEmit32.Udiv, typeof(OpCode32AluMla));
SetA32("<<<<00000100xxxxxxxxxxxx1001xxxx", InstName.Umaal, InstEmit32.Umaal, typeof(OpCode32AluUmull));
SetA32("<<<<0000101xxxxxxxxxxxxx1001xxxx", InstName.Umlal, InstEmit32.Umlal, typeof(OpCode32AluUmull));
SetA32("<<<<0000100xxxxxxxxxxxxx1001xxxx", InstName.Umull, InstEmit32.Umull, typeof(OpCode32AluUmull));
SetA32("<<<<0110111xxxxxxxxxxxxxxx01xxxx", InstName.Usat, InstEmit32.Usat, typeof(OpCode32Sat));
@ -800,12 +801,15 @@ namespace ARMeilleure.Decoders
SetA32("111100111x110000xxx0001100x0xxx0", InstName.Aese_V, InstEmit32.Aese_V, typeof(OpCode32Simd));
SetA32("111100111x110000xxx0001111x0xxx0", InstName.Aesimc_V, InstEmit32.Aesimc_V, typeof(OpCode32Simd));
SetA32("111100111x110000xxx0001110x0xxx0", InstName.Aesmc_V, InstEmit32.Aesmc_V, typeof(OpCode32Simd));
SetA32("1111001x0x<<xxxxxxxx0111xxx0xxxx", InstName.Vabd, InstEmit32.Vabd_I, typeof(OpCode32SimdReg));
SetA32("1111001x1x<<xxxxxxxx0111x0x0xxxx", InstName.Vabdl, InstEmit32.Vabdl_I, typeof(OpCode32SimdRegLong));
SetA32("<<<<11101x110000xxxx101x11x0xxxx", InstName.Vabs, InstEmit32.Vabs_S, typeof(OpCode32SimdS));
SetA32("111100111x11<<01xxxx00110xx0xxxx", InstName.Vabs, InstEmit32.Vabs_V, typeof(OpCode32SimdCmpZ));
SetA32("111100111x111001xxxx01110xx0xxxx", InstName.Vabs, InstEmit32.Vabs_V, typeof(OpCode32SimdCmpZ));
SetA32("111100100xxxxxxxxxxx1000xxx0xxxx", InstName.Vadd, InstEmit32.Vadd_I, typeof(OpCode32SimdReg));
SetA32("<<<<11100x11xxxxxxxx101xx0x0xxxx", InstName.Vadd, InstEmit32.Vadd_S, typeof(OpCode32SimdRegS));
SetA32("111100100x00xxxxxxxx1101xxx0xxxx", InstName.Vadd, InstEmit32.Vadd_V, typeof(OpCode32SimdReg));
SetA32("1111001x1x<<xxxxxxxx0000x0x0xxxx", InstName.Vaddl, InstEmit32.Vaddl_I, typeof(OpCode32SimdRegLong));
SetA32("1111001x1x<<xxxxxxxx0001x0x0xxxx", InstName.Vaddw, InstEmit32.Vaddw_I, typeof(OpCode32SimdRegWide));
SetA32("111100100x00xxxxxxxx0001xxx1xxxx", InstName.Vand, InstEmit32.Vand_I, typeof(OpCode32SimdBinary));
SetA32("111100100x01xxxxxxxx0001xxx1xxxx", InstName.Vbic, InstEmit32.Vbic_I, typeof(OpCode32SimdBinary));
@ -838,6 +842,7 @@ namespace ARMeilleure.Decoders
SetA32("111100101x11xxxxxxxxxxxxxxx0xxxx", InstName.Vext, InstEmit32.Vext, typeof(OpCode32SimdExt));
SetA32("<<<<11101x10xxxxxxxx101xx0x0xxxx", InstName.Vfma, InstEmit32.Vfma_S, typeof(OpCode32SimdRegS));
SetA32("<<<<11101x10xxxxxxxx101xx1x0xxxx", InstName.Vfms, InstEmit32.Vfms_S, typeof(OpCode32SimdRegS));
SetA32("1111001x0x<<xxxxxxxx0000xxx0xxxx", InstName.Vhadd, InstEmit32.Vhadd, typeof(OpCode32SimdReg));
SetA32("111101001x10xxxxxxxxxx00xxxxxxxx", InstName.Vld1, InstEmit32.Vld1, typeof(OpCode32SimdMemSingle));
SetA32("111101000x10xxxxxxxx0111xxxxxxxx", InstName.Vld1, InstEmit32.Vld1, typeof(OpCode32SimdMemPair)); // Regs = 1.
SetA32("111101000x10xxxxxxxx1010xxxxxxxx", InstName.Vld1, InstEmit32.Vld1, typeof(OpCode32SimdMemPair)); // Regs = 2.
@ -919,6 +924,7 @@ namespace ARMeilleure.Decoders
SetA32("111100110x10xxxxxxxx1111x0x0xxxx", InstName.Vpmin, InstEmit32.Vpmin_V, typeof(OpCode32SimdReg));
SetA32("1111001x1x>>>xxxxxxx100101x1xxx0", InstName.Vqrshrn, InstEmit32.Vqrshrn, typeof(OpCode32SimdShImmNarrow));
SetA32("111100111x>>>xxxxxxx100001x1xxx0", InstName.Vqrshrun, InstEmit32.Vqrshrun, typeof(OpCode32SimdShImmNarrow));
SetA32("1111001x1x>>>xxxxxxx100100x1xxx0", InstName.Vqshrn, InstEmit32.Vqshrn, typeof(OpCode32SimdShImmNarrow));
SetA32("111100111x111011xxxx010x0xx0xxxx", InstName.Vrecpe, InstEmit32.Vrecpe, typeof(OpCode32SimdSqrte));
SetA32("111100100x00xxxxxxxx1111xxx1xxxx", InstName.Vrecps, InstEmit32.Vrecps, typeof(OpCode32SimdReg));
SetA32("111100111x11xx00xxxx000<<xx0xxxx", InstName.Vrev, InstEmit32.Vrev, typeof(OpCode32SimdRev));
@ -930,6 +936,7 @@ namespace ARMeilleure.Decoders
SetA32("111111100xxxxxxxxxxx101xx0x0xxxx", InstName.Vsel, InstEmit32.Vsel, typeof(OpCode32SimdSel));
SetA32("111100101x>>>xxxxxxx0101>xx1xxxx", InstName.Vshl, InstEmit32.Vshl, typeof(OpCode32SimdShImm));
SetA32("1111001x0xxxxxxxxxxx0100xxx0xxxx", InstName.Vshl, InstEmit32.Vshl_I, typeof(OpCode32SimdReg));
SetA32("1111001x1x>>>xxxxxxx101000x1xxxx", InstName.Vshll, InstEmit32.Vshll, typeof(OpCode32SimdShImmLong)); // A1 encoding.
SetA32("1111001x1x>>>xxxxxxx0000>xx1xxxx", InstName.Vshr, InstEmit32.Vshr, typeof(OpCode32SimdShImm));
SetA32("111100101x>>>xxxxxxx100000x1xxx0", InstName.Vshrn, InstEmit32.Vshrn, typeof(OpCode32SimdShImmNarrow));
SetA32("<<<<11101x110001xxxx101x11x0xxxx", InstName.Vsqrt, InstEmit32.Vsqrt_S, typeof(OpCode32SimdS));

View File

@ -283,6 +283,26 @@ namespace ARMeilleure.Instructions
EmitGenericAluStoreA32(context, op.Rd, false, res);
}
public static void Umaal(ArmEmitterContext context)
{
OpCode32AluUmull op = (OpCode32AluUmull)context.CurrOp;
Operand n = context.ZeroExtend32(OperandType.I64, GetIntA32(context, op.Rn));
Operand m = context.ZeroExtend32(OperandType.I64, GetIntA32(context, op.Rm));
Operand dHi = context.ZeroExtend32(OperandType.I64, GetIntA32(context, op.RdHi));
Operand dLo = context.ZeroExtend32(OperandType.I64, GetIntA32(context, op.RdLo));
Operand res = context.Multiply(n, m);
res = context.Add(res, dHi);
res = context.Add(res, dLo);
Operand hi = context.ConvertI64ToI32(context.ShiftRightUI(res, Const(32)));
Operand lo = context.ConvertI64ToI32(res);
EmitGenericAluStoreA32(context, op.RdHi, false, hi);
EmitGenericAluStoreA32(context, op.RdLo, false, lo);
}
public static void Umlal(ArmEmitterContext context)
{
EmitMlal(context, false);

View File

@ -14,6 +14,20 @@ namespace ARMeilleure.Instructions
{
static partial class InstEmit32
{
public static void Vabd_I(ArmEmitterContext context)
{
OpCode32SimdReg op = (OpCode32SimdReg)context.CurrOp;
EmitVectorBinaryOpI32(context, (op1, op2) => EmitAbs(context, context.Subtract(op1, op2)), !op.U);
}
public static void Vabdl_I(ArmEmitterContext context)
{
OpCode32SimdRegLong op = (OpCode32SimdRegLong)context.CurrOp;
EmitVectorBinaryLongOpI32(context, (op1, op2) => EmitAbs(context, context.Subtract(op1, op2)), !op.U);
}
public static void Vabs_S(ArmEmitterContext context)
{
OpCode32SimdS op = (OpCode32SimdS)context.CurrOp;
@ -107,6 +121,13 @@ namespace ARMeilleure.Instructions
}
}
public static void Vaddl_I(ArmEmitterContext context)
{
OpCode32SimdRegLong op = (OpCode32SimdRegLong)context.CurrOp;
EmitVectorBinaryLongOpI32(context, (op1, op2) => context.Add(op1, op2), !op.U);
}
public static void Vaddw_I(ArmEmitterContext context)
{
OpCode32SimdRegWide op = (OpCode32SimdRegWide)context.CurrOp;
@ -263,6 +284,20 @@ namespace ARMeilleure.Instructions
}
}
public static void Vhadd(ArmEmitterContext context)
{
OpCode32SimdReg op = (OpCode32SimdReg)context.CurrOp;
if (op.U)
{
EmitVectorBinaryOpZx32(context, (op1, op2) => context.ShiftRightUI(context.Add(op1, op2), Const(1)));
}
else
{
EmitVectorBinaryOpSx32(context, (op1, op2) => context.ShiftRightSI(context.Add(op1, op2), Const(1)));
}
}
public static void Vmov_S(ArmEmitterContext context)
{
if (Optimizations.FastFP && Optimizations.UseSse2)

View File

@ -5,6 +5,8 @@ using System;
using System.Diagnostics;
using System.Reflection;
using static ARMeilleure.Instructions.InstEmitHelper;
using static ARMeilleure.Instructions.InstEmitSimdHelper;
using static ARMeilleure.Instructions.InstEmitSimdHelper32;
using static ARMeilleure.IntermediateRepresentation.OperandHelper;
@ -24,6 +26,13 @@ namespace ARMeilleure.Instructions
EmitRoundShrImmSaturatingNarrowOp(context, ShrImmSaturatingNarrowFlags.VectorSxZx);
}
public static void Vqshrn(ArmEmitterContext context)
{
OpCode32SimdShImm op = (OpCode32SimdShImm)context.CurrOp;
EmitShrImmSaturatingNarrowOp(context, op.U ? ShrImmSaturatingNarrowFlags.VectorZxZx : ShrImmSaturatingNarrowFlags.VectorSxSx);
}
public static void Vrshr(ArmEmitterContext context)
{
OpCode32SimdShImm op = (OpCode32SimdShImm)context.CurrOp;
@ -105,6 +114,38 @@ namespace ARMeilleure.Instructions
}
}
public static void Vshll(ArmEmitterContext context)
{
OpCode32SimdShImmLong op = (OpCode32SimdShImmLong)context.CurrOp;
Operand res = context.VectorZero();
int elems = op.GetBytesCount() >> op.Size;
for (int index = 0; index < elems; index++)
{
Operand me = EmitVectorExtract32(context, op.Qm, op.Im + index, op.Size, !op.U);
if (op.Size == 2)
{
if (op.U)
{
me = context.ZeroExtend32(OperandType.I64, me);
}
else
{
me = context.SignExtend32(OperandType.I64, me);
}
}
me = context.ShiftLeft(me, Const(op.Shift));
res = EmitVectorInsert(context, res, me, index, op.Size + 1);
}
context.Copy(GetVecA32(op.Qd), res);
}
public static void Vshr(ArmEmitterContext context)
{
OpCode32SimdShImm op = (OpCode32SimdShImm)context.CurrOp;

View File

@ -536,6 +536,7 @@ namespace ARMeilleure.Instructions
Trap,
Tst,
Ubfx,
Umaal,
Umlal,
Umull,
Usat,
@ -545,8 +546,11 @@ namespace ARMeilleure.Instructions
Uxth,
// FP & SIMD (AArch32)
Vabd,
Vabdl,
Vabs,
Vadd,
Vaddl,
Vaddw,
Vand,
Vbic,
@ -567,6 +571,7 @@ namespace ARMeilleure.Instructions
Vext,
Vfma,
Vfms,
Vhadd,
Vld1,
Vld2,
Vld3,
@ -598,11 +603,13 @@ namespace ARMeilleure.Instructions
Vpmin,
Vqrshrn,
Vqrshrun,
Vqshrn,
Vrev,
Vrint,
Vrshr,
Vsel,
Vshl,
Vshll,
Vshr,
Vshrn,
Vst1,

View File

@ -21,7 +21,7 @@ namespace ARMeilleure.Translation.PTC
{
private const string HeaderMagic = "PTChd";
private const int InternalVersion = 1447; //! To be incremented manually for each change to the ARMeilleure project.
private const int InternalVersion = 1577; //! To be incremented manually for each change to the ARMeilleure project.
private const string ActualDir = "0";
private const string BackupDir = "1";