Compare commits
3 Commits
Author | SHA1 | Date | |
---|---|---|---|
|
4505a7f162 | ||
|
ccbbaddbcb | ||
|
8bf102d2cd |
@@ -875,6 +875,7 @@ namespace ARMeilleure.Decoders
|
||||
SetVfp("<<<<11100x10xxxxxxxx101xx1x0xxxx", InstName.Vnmul, InstEmit32.Vnmul_S, OpCode32SimdRegS.Create, OpCode32SimdRegS.CreateT32);
|
||||
SetVfp("111111101x1110xxxxxx101x01x0xxxx", InstName.Vrint, InstEmit32.Vrint_RM, OpCode32SimdS.Create, OpCode32SimdS.CreateT32);
|
||||
SetVfp("<<<<11101x110110xxxx101x11x0xxxx", InstName.Vrint, InstEmit32.Vrint_Z, OpCode32SimdS.Create, OpCode32SimdS.CreateT32);
|
||||
SetVfp("<<<<11101x110110xxxx101x01x0xxxx", InstName.Vrintr, InstEmit32.Vrintr_S, OpCode32SimdS.Create, OpCode32SimdS.CreateT32);
|
||||
SetVfp("<<<<11101x110111xxxx101x01x0xxxx", InstName.Vrintx, InstEmit32.Vrintx_S, OpCode32SimdS.Create, OpCode32SimdS.CreateT32);
|
||||
SetVfp("<<<<11101x110001xxxx101x11x0xxxx", InstName.Vsqrt, InstEmit32.Vsqrt_S, OpCode32SimdS.Create, OpCode32SimdS.CreateT32);
|
||||
SetVfp("111111100xxxxxxxxxxx101xx0x0xxxx", InstName.Vsel, InstEmit32.Vsel, OpCode32SimdSel.Create, OpCode32SimdSel.CreateT32);
|
||||
@@ -995,6 +996,7 @@ namespace ARMeilleure.Decoders
|
||||
SetAsimd("1111001x1x000xxxxxxx<<x10x01xxxx", InstName.Vorr, InstEmit32.Vorr_II, OpCode32SimdImm.Create, OpCode32SimdImm.CreateT32);
|
||||
SetAsimd("111100100x<<xxxxxxxx1011x0x1xxxx", InstName.Vpadd, InstEmit32.Vpadd_I, OpCode32SimdReg.Create, OpCode32SimdReg.CreateT32);
|
||||
SetAsimd("111100110x00xxxxxxxx1101x0x0xxxx", InstName.Vpadd, InstEmit32.Vpadd_V, OpCode32SimdReg.Create, OpCode32SimdReg.CreateT32);
|
||||
SetAsimd("111100111x11<<00xxxx0110xxx0xxxx", InstName.Vpadal, InstEmit32.Vpadal, OpCode32SimdCmpZ.Create, OpCode32SimdCmpZ.CreateT32);
|
||||
SetAsimd("111100111x11<<00xxxx0010xxx0xxxx", InstName.Vpaddl, InstEmit32.Vpaddl, OpCode32SimdCmpZ.Create, OpCode32SimdCmpZ.CreateT32);
|
||||
SetAsimd("1111001x0x<<xxxxxxxx1010x0x0xxxx", InstName.Vpmax, InstEmit32.Vpmax_I, OpCode32SimdReg.Create, OpCode32SimdReg.CreateT32);
|
||||
SetAsimd("111100110x00xxxxxxxx1111x0x0xxxx", InstName.Vpmax, InstEmit32.Vpmax_V, OpCode32SimdReg.Create, OpCode32SimdReg.CreateT32);
|
||||
|
@@ -1115,6 +1115,13 @@ namespace ARMeilleure.Instructions
|
||||
}
|
||||
}
|
||||
|
||||
public static void Vpadal(ArmEmitterContext context)
|
||||
{
|
||||
OpCode32Simd op = (OpCode32Simd)context.CurrOp;
|
||||
|
||||
EmitVectorPairwiseTernaryLongOpI32(context, (op1, op2, op3) => context.Add(context.Add(op1, op2), op3), op.Opc != 1);
|
||||
}
|
||||
|
||||
public static void Vpaddl(ArmEmitterContext context)
|
||||
{
|
||||
OpCode32Simd op = (OpCode32Simd)context.CurrOp;
|
||||
|
@@ -578,6 +578,22 @@ namespace ARMeilleure.Instructions
|
||||
}
|
||||
}
|
||||
|
||||
// VRINTR (floating-point).
|
||||
public static void Vrintr_S(ArmEmitterContext context)
|
||||
{
|
||||
if (Optimizations.UseAdvSimd)
|
||||
{
|
||||
InstEmitSimdHelper32Arm64.EmitScalarUnaryOpF32(context, Intrinsic.Arm64FrintiS);
|
||||
}
|
||||
else
|
||||
{
|
||||
EmitScalarUnaryOpF32(context, (op1) =>
|
||||
{
|
||||
return EmitRoundByRMode(context, op1);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// VRINTZ (floating-point).
|
||||
public static void Vrint_Z(ArmEmitterContext context)
|
||||
{
|
||||
|
@@ -673,6 +673,35 @@ namespace ARMeilleure.Instructions
|
||||
context.Copy(GetVecA32(op.Qd), res);
|
||||
}
|
||||
|
||||
public static void EmitVectorPairwiseTernaryLongOpI32(ArmEmitterContext context, Func3I emit, bool signed)
|
||||
{
|
||||
OpCode32Simd op = (OpCode32Simd)context.CurrOp;
|
||||
|
||||
int elems = op.GetBytesCount() >> op.Size;
|
||||
int pairs = elems >> 1;
|
||||
|
||||
Operand res = GetVecA32(op.Qd);
|
||||
|
||||
for (int index = 0; index < pairs; index++)
|
||||
{
|
||||
int pairIndex = index * 2;
|
||||
Operand m1 = EmitVectorExtract32(context, op.Qm, op.Im + pairIndex, op.Size, signed);
|
||||
Operand m2 = EmitVectorExtract32(context, op.Qm, op.Im + pairIndex + 1, op.Size, signed);
|
||||
|
||||
if (op.Size == 2)
|
||||
{
|
||||
m1 = signed ? context.SignExtend32(OperandType.I64, m1) : context.ZeroExtend32(OperandType.I64, m1);
|
||||
m2 = signed ? context.SignExtend32(OperandType.I64, m2) : context.ZeroExtend32(OperandType.I64, m2);
|
||||
}
|
||||
|
||||
Operand d1 = EmitVectorExtract32(context, op.Qd, op.Id + index, op.Size + 1, signed);
|
||||
|
||||
res = EmitVectorInsert(context, res, emit(m1, m2, d1), op.Id + index, op.Size + 1);
|
||||
}
|
||||
|
||||
context.Copy(GetVecA32(op.Qd), res);
|
||||
}
|
||||
|
||||
// Narrow
|
||||
|
||||
public static void EmitVectorUnaryNarrowOp32(ArmEmitterContext context, Func1I emit, bool signed = false)
|
||||
|
@@ -637,6 +637,7 @@ namespace ARMeilleure.Instructions
|
||||
Vorn,
|
||||
Vorr,
|
||||
Vpadd,
|
||||
Vpadal,
|
||||
Vpaddl,
|
||||
Vpmax,
|
||||
Vpmin,
|
||||
@@ -656,6 +657,7 @@ namespace ARMeilleure.Instructions
|
||||
Vrintm,
|
||||
Vrintn,
|
||||
Vrintp,
|
||||
Vrintr,
|
||||
Vrintx,
|
||||
Vrshr,
|
||||
Vrshrn,
|
||||
|
@@ -1352,9 +1352,9 @@ namespace Ryujinx.Ava.UI.ViewModels
|
||||
{
|
||||
string logPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Logs");
|
||||
|
||||
if (ReleaseInformation.IsValid)
|
||||
if (LoggerModule.LogDirectoryPath != null)
|
||||
{
|
||||
logPath = Path.Combine(AppDataManager.BaseDirPath, "Logs");
|
||||
logPath = LoggerModule.LogDirectoryPath;
|
||||
}
|
||||
|
||||
new DirectoryInfo(logPath).Create();
|
||||
|
@@ -23,7 +23,7 @@ namespace Ryujinx.Common.Logging.Targets
|
||||
public static FileStream PrepareLogFile(string path)
|
||||
{
|
||||
// Ensure directory is present
|
||||
DirectoryInfo logDir = new(Path.Combine(path, "Logs"));
|
||||
DirectoryInfo logDir = new(path);
|
||||
try
|
||||
{
|
||||
logDir.Create();
|
||||
|
@@ -427,11 +427,11 @@ namespace Ryujinx.Headless.SDL2
|
||||
|
||||
if (!option.DisableFileLog)
|
||||
{
|
||||
FileStream logFile = FileLogTarget.PrepareLogFile(AppDomain.CurrentDomain.BaseDirectory);
|
||||
FileStream logFile = FileLogTarget.PrepareLogFile(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Logs"));
|
||||
|
||||
if (logFile == null)
|
||||
{
|
||||
logFile = FileLogTarget.PrepareLogFile(AppDataManager.BaseDirPath);
|
||||
logFile = FileLogTarget.PrepareLogFile(Path.Combine(AppDataManager.BaseDirPath, "Logs"));
|
||||
|
||||
if (logFile == null)
|
||||
{
|
||||
|
@@ -181,6 +181,7 @@ namespace Ryujinx.Horizon.Sdk.Sf.Hipc
|
||||
}
|
||||
|
||||
Span<uint> dataWords = Span<uint>.Empty;
|
||||
Span<uint> dataWordsPadded = Span<uint>.Empty;
|
||||
|
||||
if (meta.DataWordsCount != 0)
|
||||
{
|
||||
@@ -189,6 +190,7 @@ namespace Ryujinx.Horizon.Sdk.Sf.Hipc
|
||||
int padding = (dataOffsetAligned - dataOffset) / sizeof(uint);
|
||||
|
||||
dataWords = MemoryMarshal.Cast<byte, uint>(data)[padding..meta.DataWordsCount];
|
||||
dataWordsPadded = MemoryMarshal.Cast<byte, uint>(data)[..meta.DataWordsCount];
|
||||
|
||||
data = data[(meta.DataWordsCount * sizeof(uint))..];
|
||||
}
|
||||
@@ -209,6 +211,7 @@ namespace Ryujinx.Horizon.Sdk.Sf.Hipc
|
||||
ReceiveBuffers = receiveBuffers,
|
||||
ExchangeBuffers = exchangeBuffers,
|
||||
DataWords = dataWords,
|
||||
DataWordsPadded = dataWordsPadded,
|
||||
ReceiveList = receiveList,
|
||||
CopyHandles = copyHandles,
|
||||
MoveHandles = moveHandles,
|
||||
|
@@ -9,6 +9,7 @@ namespace Ryujinx.Horizon.Sdk.Sf.Hipc
|
||||
public Span<HipcBufferDescriptor> ReceiveBuffers;
|
||||
public Span<HipcBufferDescriptor> ExchangeBuffers;
|
||||
public Span<uint> DataWords;
|
||||
public Span<uint> DataWordsPadded;
|
||||
public Span<HipcReceiveListEntry> ReceiveList;
|
||||
public Span<int> CopyHandles;
|
||||
public Span<int> MoveHandles;
|
||||
|
@@ -206,7 +206,7 @@ namespace Ryujinx.Horizon.Sdk.Sf
|
||||
}
|
||||
else
|
||||
{
|
||||
var data = MemoryMarshal.Cast<uint, byte>(context.Request.Data.DataWords);
|
||||
var data = MemoryMarshal.Cast<uint, byte>(context.Request.Data.DataWordsPadded);
|
||||
var recvPointerSizes = MemoryMarshal.Cast<byte, ushort>(data[runtimeMetadata.UnfixedOutPointerSizeOffset..]);
|
||||
|
||||
size = recvPointerSizes[unfixedRecvPointerIndex++];
|
||||
|
@@ -511,6 +511,45 @@ namespace Ryujinx.Tests.Cpu
|
||||
|
||||
CompareAgainstUnicorn();
|
||||
}
|
||||
|
||||
[Test, Pairwise, Description("VRINTR.F<size> <Sd>, <Sm>")]
|
||||
[Platform(Exclude = "Linux,MacOsX")] // Instruction isn't testable due to Unicorn.
|
||||
public void Vrintr([Values(0u, 1u)] uint rd,
|
||||
[Values(0u, 1u)] uint rm,
|
||||
[Values(2u, 3u)] uint size,
|
||||
[ValueSource(nameof(_1D_F_))] ulong s0,
|
||||
[ValueSource(nameof(_1D_F_))] ulong s1,
|
||||
[ValueSource(nameof(_1D_F_))] ulong s2,
|
||||
[Values(RMode.Rn, RMode.Rm, RMode.Rp)] RMode rMode)
|
||||
{
|
||||
uint opcode = 0xEEB60A40;
|
||||
|
||||
V128 v0, v1, v2;
|
||||
|
||||
if (size == 2)
|
||||
{
|
||||
opcode |= ((rm & 0x1e) >> 1) | ((rm & 0x1) << 5);
|
||||
opcode |= ((rd & 0x1e) << 11) | ((rd & 0x1) << 22);
|
||||
v0 = MakeVectorE0E1((uint)BitConverter.SingleToInt32Bits(s0), (uint)BitConverter.SingleToInt32Bits(s0));
|
||||
v1 = MakeVectorE0E1((uint)BitConverter.SingleToInt32Bits(s1), (uint)BitConverter.SingleToInt32Bits(s0));
|
||||
v2 = MakeVectorE0E1((uint)BitConverter.SingleToInt32Bits(s2), (uint)BitConverter.SingleToInt32Bits(s1));
|
||||
}
|
||||
else
|
||||
{
|
||||
opcode |= ((rm & 0xf) << 0) | ((rm & 0x10) << 1);
|
||||
opcode |= ((rd & 0xf) << 12) | ((rd & 0x10) << 18);
|
||||
v0 = MakeVectorE0E1((uint)BitConverter.DoubleToInt64Bits(s0), (uint)BitConverter.DoubleToInt64Bits(s0));
|
||||
v1 = MakeVectorE0E1((uint)BitConverter.DoubleToInt64Bits(s1), (uint)BitConverter.DoubleToInt64Bits(s0));
|
||||
v2 = MakeVectorE0E1((uint)BitConverter.DoubleToInt64Bits(s2), (uint)BitConverter.DoubleToInt64Bits(s1));
|
||||
}
|
||||
|
||||
opcode |= ((size & 3) << 8);
|
||||
|
||||
int fpscr = (int)rMode << (int)Fpcr.RMode;
|
||||
SingleOpcode(opcode, v0: v0, v1: v1, v2: v2, fpscr: fpscr);
|
||||
|
||||
CompareAgainstUnicorn();
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
@@ -908,6 +908,44 @@ namespace Ryujinx.Tests.Cpu
|
||||
|
||||
CompareAgainstUnicorn();
|
||||
}
|
||||
|
||||
[Test, Pairwise]
|
||||
public void Vp_Add_Long_Accumulate([Values(0u, 2u, 4u, 8u)] uint rd,
|
||||
[Values(0u, 2u, 4u, 8u)] uint rm,
|
||||
[Values(0u, 1u, 2u)] uint size,
|
||||
[Random(RndCnt)] ulong z,
|
||||
[Random(RndCnt)] ulong a,
|
||||
[Random(RndCnt)] ulong b,
|
||||
[Values] bool q,
|
||||
[Values] bool unsigned)
|
||||
{
|
||||
uint opcode = 0xF3B00600; // VPADAL.S8 D0, Q0
|
||||
|
||||
if (q)
|
||||
{
|
||||
opcode |= 1 << 6;
|
||||
rm <<= 1;
|
||||
rd <<= 1;
|
||||
}
|
||||
|
||||
if (unsigned)
|
||||
{
|
||||
opcode |= 1 << 7;
|
||||
}
|
||||
|
||||
opcode |= ((rm & 0xf) << 0) | ((rm & 0x10) << 1);
|
||||
opcode |= ((rd & 0xf) << 12) | ((rd & 0x10) << 18);
|
||||
|
||||
opcode |= size << 18;
|
||||
|
||||
V128 v0 = MakeVectorE0E1(z, z);
|
||||
V128 v1 = MakeVectorE0E1(a, z);
|
||||
V128 v2 = MakeVectorE0E1(b, z);
|
||||
|
||||
SingleOpcode(opcode, v0: v0, v1: v1, v2: v2);
|
||||
|
||||
CompareAgainstUnicorn();
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
@@ -9,6 +9,8 @@ namespace Ryujinx.Ui.Common.Configuration
|
||||
{
|
||||
public static class LoggerModule
|
||||
{
|
||||
public static string LogDirectoryPath { get; private set; }
|
||||
|
||||
public static void Initialize()
|
||||
{
|
||||
ConfigurationState.Instance.Logger.EnableDebug.Event += ReloadEnableDebug;
|
||||
@@ -82,21 +84,26 @@ namespace Ryujinx.Ui.Common.Configuration
|
||||
{
|
||||
if (e.NewValue)
|
||||
{
|
||||
FileStream logFile = FileLogTarget.PrepareLogFile(AppDomain.CurrentDomain.BaseDirectory);
|
||||
string logDir = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Logs");
|
||||
FileStream logFile = FileLogTarget.PrepareLogFile(logDir);
|
||||
|
||||
if (logFile == null)
|
||||
{
|
||||
logFile = FileLogTarget.PrepareLogFile(AppDataManager.BaseDirPath);
|
||||
logDir = Path.Combine(AppDataManager.BaseDirPath, "Logs");
|
||||
logFile = FileLogTarget.PrepareLogFile(logDir);
|
||||
|
||||
if (logFile == null)
|
||||
{
|
||||
Logger.Error?.Print(LogClass.Application, "No writable log directory available. Make sure either the application directory or the Ryujinx directory is writable.");
|
||||
LogDirectoryPath = null;
|
||||
Logger.RemoveTarget("file");
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
LogDirectoryPath = logDir;
|
||||
|
||||
Logger.AddTarget(new AsyncLogTargetWrapper(
|
||||
new FileLogTarget("file", logFile),
|
||||
1000,
|
||||
|
@@ -1378,9 +1378,9 @@ namespace Ryujinx.Ui
|
||||
{
|
||||
string logPath = System.IO.Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Logs");
|
||||
|
||||
if (ReleaseInformation.IsValid)
|
||||
if (LoggerModule.LogDirectoryPath != null)
|
||||
{
|
||||
logPath = System.IO.Path.Combine(AppDataManager.BaseDirPath, "Logs");
|
||||
logPath = LoggerModule.LogDirectoryPath;
|
||||
}
|
||||
|
||||
new DirectoryInfo(logPath).Create();
|
||||
|
Reference in New Issue
Block a user