mirror of
https://github.com/ryujinx-mirror/ryujinx.git
synced 2024-10-02 16:50:20 -07:00

* Implement a new JIT for Arm devices * Auto-format * Make a lot of Assembler members read-only * More read-only * Fix more warnings * ObjectDisposedException.ThrowIf * New JIT cache for platforms that enforce W^X, currently unused * Remove unused using * Fix assert * Pass memory manager type around * Safe memory manager mode support + other improvements * Actual safe memory manager mode masking support * PR feedback
206 lines
9.1 KiB
C#
206 lines
9.1 KiB
C#
using System.Diagnostics;
|
|
|
|
namespace Ryujinx.Cpu.LightningJit.Arm32.Target.Arm64
|
|
{
|
|
static class InstEmitNeonSaturate
|
|
{
|
|
public static void Vqabs(CodeGenContext context, uint rd, uint rm, uint size, uint q)
|
|
{
|
|
InstEmitNeonCommon.EmitVectorUnary(context, rd, rm, size, q, context.Arm64Assembler.SqabsV);
|
|
}
|
|
|
|
public static void Vqadd(CodeGenContext context, uint rd, uint rn, uint rm, bool u, uint size, uint q)
|
|
{
|
|
InstEmitNeonCommon.EmitVectorBinary(
|
|
context,
|
|
rd,
|
|
rn,
|
|
rm,
|
|
size,
|
|
q,
|
|
u ? context.Arm64Assembler.UqaddV : context.Arm64Assembler.SqaddV,
|
|
u ? context.Arm64Assembler.UqaddS : context.Arm64Assembler.SqaddS);
|
|
}
|
|
|
|
public static void Vqdmlal(CodeGenContext context, uint rd, uint rn, uint rm, uint size)
|
|
{
|
|
InstEmitNeonCommon.EmitVectorBinaryLong(context, rd, rn, rm, size, context.Arm64Assembler.SqdmlalVecV);
|
|
}
|
|
|
|
public static void VqdmlalS(CodeGenContext context, uint rd, uint rn, uint rm, uint size)
|
|
{
|
|
InstEmitNeonCommon.EmitVectorBinaryLongByScalar(context, rd, rn, rm, size, context.Arm64Assembler.SqdmlalElt2regElement);
|
|
}
|
|
|
|
public static void Vqdmlsl(CodeGenContext context, uint rd, uint rn, uint rm, uint size)
|
|
{
|
|
InstEmitNeonCommon.EmitVectorBinaryLong(context, rd, rn, rm, size, context.Arm64Assembler.SqdmlslVecV);
|
|
}
|
|
|
|
public static void VqdmlslS(CodeGenContext context, uint rd, uint rn, uint rm, uint size)
|
|
{
|
|
InstEmitNeonCommon.EmitVectorBinaryLongByScalar(context, rd, rn, rm, size, context.Arm64Assembler.SqdmlslElt2regElement);
|
|
}
|
|
|
|
public static void Vqdmulh(CodeGenContext context, uint rd, uint rn, uint rm, uint size, uint q)
|
|
{
|
|
InstEmitNeonCommon.EmitVectorBinary(context, rd, rn, rm, size, q, context.Arm64Assembler.SqdmulhVecV, context.Arm64Assembler.SqdmulhVecS);
|
|
}
|
|
|
|
public static void VqdmulhS(CodeGenContext context, uint rd, uint rn, uint rm, uint size, uint q)
|
|
{
|
|
InstEmitNeonCommon.EmitVectorBinaryByScalar(context, rd, rn, rm, size, q, context.Arm64Assembler.SqdmulhElt2regElement);
|
|
}
|
|
|
|
public static void Vqdmull(CodeGenContext context, uint rd, uint rn, uint rm, uint size)
|
|
{
|
|
InstEmitNeonCommon.EmitVectorBinaryLong(context, rd, rn, rm, size, context.Arm64Assembler.SqdmullVecV);
|
|
}
|
|
|
|
public static void VqdmullS(CodeGenContext context, uint rd, uint rn, uint rm, uint size)
|
|
{
|
|
InstEmitNeonCommon.EmitVectorBinaryLongByScalar(context, rd, rn, rm, size, context.Arm64Assembler.SqdmullElt2regElement);
|
|
}
|
|
|
|
public static void Vqmovn(CodeGenContext context, uint rd, uint rm, uint op, uint size)
|
|
{
|
|
if (op == 3)
|
|
{
|
|
InstEmitNeonCommon.EmitVectorUnaryNarrow(context, rd, rm, size, context.Arm64Assembler.UqxtnV);
|
|
}
|
|
else
|
|
{
|
|
InstEmitNeonCommon.EmitVectorUnaryNarrow(context, rd, rm, size, op == 1 ? context.Arm64Assembler.SqxtunV : context.Arm64Assembler.SqxtnV);
|
|
}
|
|
}
|
|
|
|
public static void Vqneg(CodeGenContext context, uint rd, uint rm, uint size, uint q)
|
|
{
|
|
InstEmitNeonCommon.EmitVectorUnary(context, rd, rm, size, q, context.Arm64Assembler.SqnegV);
|
|
}
|
|
|
|
public static void Vqrdmlah(CodeGenContext context, uint rd, uint rn, uint rm, uint size, uint q)
|
|
{
|
|
InstEmitNeonCommon.EmitVectorTernaryRd(context, rd, rn, rm, size, q, context.Arm64Assembler.SqrdmlahVecV);
|
|
}
|
|
|
|
public static void VqrdmlahS(CodeGenContext context, uint rd, uint rn, uint rm, uint size, uint q)
|
|
{
|
|
InstEmitNeonCommon.EmitVectorTernaryRdByScalar(context, rd, rn, rm, size, q, context.Arm64Assembler.SqrdmlahElt2regElement);
|
|
}
|
|
|
|
public static void Vqrdmlsh(CodeGenContext context, uint rd, uint rn, uint rm, uint size, uint q)
|
|
{
|
|
InstEmitNeonCommon.EmitVectorTernaryRd(context, rd, rn, rm, size, q, context.Arm64Assembler.SqrdmlshVecV);
|
|
}
|
|
|
|
public static void VqrdmlshS(CodeGenContext context, uint rd, uint rn, uint rm, uint size, uint q)
|
|
{
|
|
InstEmitNeonCommon.EmitVectorTernaryRdByScalar(context, rd, rn, rm, size, q, context.Arm64Assembler.SqrdmlshElt2regElement);
|
|
}
|
|
|
|
public static void Vqrdmulh(CodeGenContext context, uint rd, uint rn, uint rm, uint size, uint q)
|
|
{
|
|
InstEmitNeonCommon.EmitVectorBinary(context, rd, rn, rm, size, q, context.Arm64Assembler.SqrdmulhVecV, context.Arm64Assembler.SqrdmulhVecS);
|
|
}
|
|
|
|
public static void VqrdmulhS(CodeGenContext context, uint rd, uint rn, uint rm, uint size, uint q)
|
|
{
|
|
InstEmitNeonCommon.EmitVectorBinaryByScalar(context, rd, rn, rm, size, q, context.Arm64Assembler.SqrdmulhElt2regElement);
|
|
}
|
|
|
|
public static void Vqrshl(CodeGenContext context, uint rd, uint rn, uint rm, uint size, uint q)
|
|
{
|
|
InstEmitNeonCommon.EmitVectorBinary(context, rd, rm, rn, size, q, context.Arm64Assembler.SqrshlV, context.Arm64Assembler.SqrshlS);
|
|
}
|
|
|
|
public static void Vqrshrn(CodeGenContext context, uint rd, uint rm, bool u, uint op, uint imm6)
|
|
{
|
|
uint size = InstEmitNeonCommon.GetSizeFromImm6(imm6);
|
|
uint shift = InstEmitNeonShift.GetShiftRight(imm6, size);
|
|
|
|
if (u && op == 0)
|
|
{
|
|
InstEmitNeonCommon.EmitVectorBinaryNarrowShift(context, rd, rm, shift, size, isShl: false, context.Arm64Assembler.SqrshrunV);
|
|
}
|
|
else if (!u && op == 1)
|
|
{
|
|
InstEmitNeonCommon.EmitVectorBinaryNarrowShift(context, rd, rm, shift, size, isShl: false, context.Arm64Assembler.SqrshrnV);
|
|
}
|
|
else
|
|
{
|
|
Debug.Assert(u && op == 1); // !u && op == 0 is the encoding for another instruction.
|
|
|
|
InstEmitNeonCommon.EmitVectorBinaryNarrowShift(context, rd, rm, shift, size, isShl: false, context.Arm64Assembler.UqrshrnV);
|
|
}
|
|
}
|
|
|
|
public static void VqshlI(CodeGenContext context, uint rd, uint rm, bool u, uint op, uint l, uint imm6, uint q)
|
|
{
|
|
uint size = InstEmitNeonCommon.GetSizeFromImm7(imm6 | (l << 6));
|
|
uint shift = InstEmitNeonShift.GetShiftLeft(imm6, size);
|
|
|
|
if (u && op == 0)
|
|
{
|
|
InstEmitNeonCommon.EmitVectorBinaryShift(context, rd, rm, shift, size, q, isShl: true, context.Arm64Assembler.SqshluV, context.Arm64Assembler.SqshluS);
|
|
}
|
|
else if (!u && op == 1)
|
|
{
|
|
InstEmitNeonCommon.EmitVectorBinaryShift(context, rd, rm, shift, size, q, isShl: true, context.Arm64Assembler.SqshlImmV, context.Arm64Assembler.SqshlImmS);
|
|
}
|
|
else
|
|
{
|
|
Debug.Assert(u && op == 1); // !u && op == 0 is the encoding for another instruction.
|
|
|
|
InstEmitNeonCommon.EmitVectorBinaryShift(context, rd, rm, shift, size, q, isShl: true, context.Arm64Assembler.UqshlImmV, context.Arm64Assembler.UqshlImmS);
|
|
}
|
|
}
|
|
|
|
public static void VqshlR(CodeGenContext context, uint rd, uint rn, uint rm, bool u, uint size, uint q)
|
|
{
|
|
if (u)
|
|
{
|
|
InstEmitNeonCommon.EmitVectorBinary(context, rd, rm, rn, size, q, context.Arm64Assembler.UqshlRegV, context.Arm64Assembler.UqshlRegS);
|
|
}
|
|
else
|
|
{
|
|
InstEmitNeonCommon.EmitVectorBinary(context, rd, rm, rn, size, q, context.Arm64Assembler.SqshlRegV, context.Arm64Assembler.SqshlRegS);
|
|
}
|
|
}
|
|
|
|
public static void Vqshrn(CodeGenContext context, uint rd, uint rm, bool u, uint op, uint imm6)
|
|
{
|
|
uint size = InstEmitNeonCommon.GetSizeFromImm6(imm6);
|
|
uint shift = InstEmitNeonShift.GetShiftRight(imm6, size);
|
|
|
|
if (u && op == 0)
|
|
{
|
|
InstEmitNeonCommon.EmitVectorBinaryNarrowShift(context, rd, rm, shift, size, isShl: false, context.Arm64Assembler.SqshrunV);
|
|
}
|
|
else if (!u && op == 1)
|
|
{
|
|
InstEmitNeonCommon.EmitVectorBinaryNarrowShift(context, rd, rm, shift, size, isShl: false, context.Arm64Assembler.SqshrnV);
|
|
}
|
|
else
|
|
{
|
|
Debug.Assert(u && op == 1); // !u && op == 0 is the encoding for another instruction.
|
|
|
|
InstEmitNeonCommon.EmitVectorBinaryNarrowShift(context, rd, rm, shift, size, isShl: false, context.Arm64Assembler.UqshrnV);
|
|
}
|
|
}
|
|
|
|
public static void Vqsub(CodeGenContext context, uint rd, uint rn, uint rm, bool u, uint size, uint q)
|
|
{
|
|
InstEmitNeonCommon.EmitVectorBinary(
|
|
context,
|
|
rd,
|
|
rn,
|
|
rm,
|
|
size,
|
|
q,
|
|
u ? context.Arm64Assembler.UqsubV : context.Arm64Assembler.SqsubV,
|
|
u ? context.Arm64Assembler.UqsubS : context.Arm64Assembler.SqsubS);
|
|
}
|
|
}
|
|
}
|