commit
9a5b9b2dd3
21 changed files with 700 additions and 337 deletions
|
@ -351,7 +351,9 @@ void main(void) {
|
||||||
protected override void OnRenderFrame(FrameEventArgs e)
|
protected override void OnRenderFrame(FrameEventArgs e)
|
||||||
{
|
{
|
||||||
GL.Viewport(0, 0, 1280, 720);
|
GL.Viewport(0, 0, 1280, 720);
|
||||||
|
|
||||||
|
Title = $"Ryujinx Screen - (Vsync: {VSync} - FPS: {1f / e.Time:0})";
|
||||||
|
|
||||||
GL.Clear(ClearBufferMask.ColorBufferBit | ClearBufferMask.DepthBufferBit);
|
GL.Clear(ClearBufferMask.ColorBufferBit | ClearBufferMask.DepthBufferBit);
|
||||||
|
|
||||||
RenderFb();
|
RenderFb();
|
||||||
|
|
15
Program.cs
15
Program.cs
|
@ -9,6 +9,10 @@ namespace Ryujinx
|
||||||
{
|
{
|
||||||
static void Main(string[] args)
|
static void Main(string[] args)
|
||||||
{
|
{
|
||||||
|
Config.Read();
|
||||||
|
|
||||||
|
Console.Title = "Ryujinx Console";
|
||||||
|
|
||||||
IGalRenderer Renderer = new OpenGLRenderer();
|
IGalRenderer Renderer = new OpenGLRenderer();
|
||||||
|
|
||||||
Switch Ns = new Switch(Renderer);
|
Switch Ns = new Switch(Renderer);
|
||||||
|
@ -21,27 +25,30 @@ namespace Ryujinx
|
||||||
|
|
||||||
if (RomFsFiles.Length > 0)
|
if (RomFsFiles.Length > 0)
|
||||||
{
|
{
|
||||||
Console.WriteLine("Loading as cart with RomFS.");
|
Logging.Info("Loading as cart with RomFS.");
|
||||||
|
|
||||||
|
Console.Title += " - Cart (with RomFS) - " + args[0];
|
||||||
Ns.Os.LoadCart(args[0], RomFsFiles[0]);
|
Ns.Os.LoadCart(args[0], RomFsFiles[0]);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Console.WriteLine("Loading as cart WITHOUT RomFS.");
|
Logging.Info("Loading as cart WITHOUT RomFS.");
|
||||||
|
|
||||||
|
Console.Title += " - Cart (without RomFS) - " + args[0];
|
||||||
Ns.Os.LoadCart(args[0]);
|
Ns.Os.LoadCart(args[0]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (File.Exists(args[0]))
|
else if (File.Exists(args[0]))
|
||||||
{
|
{
|
||||||
Console.WriteLine("Loading as homebrew.");
|
Logging.Info("Loading as homebrew.");
|
||||||
|
|
||||||
|
Console.Title += " - Homebrew - " + args[0];
|
||||||
Ns.Os.LoadProgram(args[0]);
|
Ns.Os.LoadProgram(args[0]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Console.WriteLine("Please specify the folder with the NSOs/IStorage or a NSO/NRO.");
|
Logging.Error("Please specify the folder with the NSOs/IStorage or a NSO/NRO.");
|
||||||
}
|
}
|
||||||
|
|
||||||
using (GLScreen Screen = new GLScreen(Ns, Renderer))
|
using (GLScreen Screen = new GLScreen(Ns, Renderer))
|
||||||
|
|
20
Ryujinx.conf
Normal file
20
Ryujinx.conf
Normal file
|
@ -0,0 +1,20 @@
|
||||||
|
#Enabled print informations logs
|
||||||
|
Logging_Enable_Info = true
|
||||||
|
|
||||||
|
#Enabled print trace logs
|
||||||
|
Logging_Enable_Trace = true
|
||||||
|
|
||||||
|
#Enabled print debug logs
|
||||||
|
Logging_Enable_Debug = true
|
||||||
|
|
||||||
|
#Enabled print warning logs
|
||||||
|
Logging_Enable_Warn = true
|
||||||
|
|
||||||
|
#Enabled print error logs
|
||||||
|
Logging_Enable_Error = true
|
||||||
|
|
||||||
|
#Enabled print fatal logs
|
||||||
|
Logging_Enable_Fatal = true
|
||||||
|
|
||||||
|
#Saved logs into Ryujinx.log
|
||||||
|
Logging_Enable_LogFile = false
|
|
@ -9,4 +9,9 @@
|
||||||
<PackageReference Include="OpenTK.NETCore" Version="1.1.2749.6433" />
|
<PackageReference Include="OpenTK.NETCore" Version="1.1.2749.6433" />
|
||||||
<PackageReference Include="System.Runtime.CompilerServices.Unsafe" Version="4.4.0" />
|
<PackageReference Include="System.Runtime.CompilerServices.Unsafe" Version="4.4.0" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<None Update="Ryujinx.conf">
|
||||||
|
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||||
|
</None>
|
||||||
|
</ItemGroup>
|
||||||
</Project>
|
</Project>
|
55
Ryujinx/Config.cs
Normal file
55
Ryujinx/Config.cs
Normal file
|
@ -0,0 +1,55 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.IO;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Reflection;
|
||||||
|
|
||||||
|
namespace Ryujinx
|
||||||
|
{
|
||||||
|
public static class Config
|
||||||
|
{
|
||||||
|
public static bool LoggingEnableInfo { get; private set; }
|
||||||
|
public static bool LoggingEnableTrace { get; private set; }
|
||||||
|
public static bool LoggingEnableDebug { get; private set; }
|
||||||
|
public static bool LoggingEnableWarn { get; private set; }
|
||||||
|
public static bool LoggingEnableError { get; private set; }
|
||||||
|
public static bool LoggingEnableFatal { get; private set; }
|
||||||
|
public static bool LoggingEnableLogFile { get; private set; }
|
||||||
|
|
||||||
|
public static void Read()
|
||||||
|
{
|
||||||
|
IniParser Parser = new IniParser(Path.Combine(Path.GetDirectoryName(Assembly.GetEntryAssembly().Location), "Ryujinx.conf"));
|
||||||
|
|
||||||
|
LoggingEnableInfo = Convert.ToBoolean(Parser.Value("Logging_Enable_Info"));
|
||||||
|
LoggingEnableTrace = Convert.ToBoolean(Parser.Value("Logging_Enable_Trace"));
|
||||||
|
LoggingEnableDebug = Convert.ToBoolean(Parser.Value("Logging_Enable_Debug"));
|
||||||
|
LoggingEnableWarn = Convert.ToBoolean(Parser.Value("Logging_Enable_Warn"));
|
||||||
|
LoggingEnableError = Convert.ToBoolean(Parser.Value("Logging_Enable_Error"));
|
||||||
|
LoggingEnableFatal = Convert.ToBoolean(Parser.Value("Logging_Enable_Fatal"));
|
||||||
|
LoggingEnableLogFile = Convert.ToBoolean(Parser.Value("Logging_Enable_LogFile"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// https://stackoverflow.com/a/37772571
|
||||||
|
public class IniParser
|
||||||
|
{
|
||||||
|
private Dictionary<string, string> Values;
|
||||||
|
|
||||||
|
public IniParser(string Path)
|
||||||
|
{
|
||||||
|
Values = File.ReadLines(Path)
|
||||||
|
.Where(Line => (!String.IsNullOrWhiteSpace(Line) && !Line.StartsWith("#")))
|
||||||
|
.Select(Line => Line.Split(new char[] { '=' }, 2, 0))
|
||||||
|
.ToDictionary(Parts => Parts[0].Trim(), Parts => Parts.Length > 1 ? Parts[1].Trim() : null);
|
||||||
|
}
|
||||||
|
|
||||||
|
public string Value(string Name, string Value = null)
|
||||||
|
{
|
||||||
|
if (Values != null && Values.ContainsKey(Name))
|
||||||
|
{
|
||||||
|
return Values[Name];
|
||||||
|
}
|
||||||
|
return Value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -152,12 +152,13 @@ namespace ChocolArm64
|
||||||
Set("x0011110xx110000000000xxxxxxxxxx", AInstEmit.Fcvtms_S, typeof(AOpCodeSimdCvt));
|
Set("x0011110xx110000000000xxxxxxxxxx", AInstEmit.Fcvtms_S, typeof(AOpCodeSimdCvt));
|
||||||
Set("x0011110xx101000000000xxxxxxxxxx", AInstEmit.Fcvtps_S, typeof(AOpCodeSimdCvt));
|
Set("x0011110xx101000000000xxxxxxxxxx", AInstEmit.Fcvtps_S, typeof(AOpCodeSimdCvt));
|
||||||
Set("x0011110xx111000000000xxxxxxxxxx", AInstEmit.Fcvtzs_S, typeof(AOpCodeSimdCvt));
|
Set("x0011110xx111000000000xxxxxxxxxx", AInstEmit.Fcvtzs_S, typeof(AOpCodeSimdCvt));
|
||||||
Set("0x0011101x100001101110xxxxxxxxxx", AInstEmit.Fcvtzs_V, typeof(AOpCodeSimd));
|
|
||||||
Set("x0011110xx111001000000xxxxxxxxxx", AInstEmit.Fcvtzu_S, typeof(AOpCodeSimdCvt));
|
|
||||||
Set("0x1011101x100001101110xxxxxxxxxx", AInstEmit.Fcvtzu_V, typeof(AOpCodeSimd));
|
|
||||||
Set("0x1011110>>xxxxx111111xxxxxxxxxx", AInstEmit.Fcvtzu_V_Fix, typeof(AOpCodeSimdShImm));
|
|
||||||
Set("x0011110xx011000xxxxxxxxxxxxxxxx", AInstEmit.Fcvtzs_Fix, typeof(AOpCodeSimdCvt));
|
Set("x0011110xx011000xxxxxxxxxxxxxxxx", AInstEmit.Fcvtzs_Fix, typeof(AOpCodeSimdCvt));
|
||||||
|
Set("0x0011101x100001101110xxxxxxxxxx", AInstEmit.Fcvtzs_V, typeof(AOpCodeSimd));
|
||||||
|
Set("0x0011110>>xxxxx111111xxxxxxxxxx", AInstEmit.Fcvtzs_V, typeof(AOpCodeSimdShImm));
|
||||||
|
Set("x0011110xx111001000000xxxxxxxxxx", AInstEmit.Fcvtzu_S, typeof(AOpCodeSimdCvt));
|
||||||
Set("x0011110xx011001xxxxxxxxxxxxxxxx", AInstEmit.Fcvtzu_Fix, typeof(AOpCodeSimdCvt));
|
Set("x0011110xx011001xxxxxxxxxxxxxxxx", AInstEmit.Fcvtzu_Fix, typeof(AOpCodeSimdCvt));
|
||||||
|
Set("0x1011101x100001101110xxxxxxxxxx", AInstEmit.Fcvtzu_V, typeof(AOpCodeSimd));
|
||||||
|
Set("0x1011110>>xxxxx111111xxxxxxxxxx", AInstEmit.Fcvtzu_V, typeof(AOpCodeSimdShImm));
|
||||||
Set("00011110xx1xxxxx000110xxxxxxxxxx", AInstEmit.Fdiv_S, typeof(AOpCodeSimdReg));
|
Set("00011110xx1xxxxx000110xxxxxxxxxx", AInstEmit.Fdiv_S, typeof(AOpCodeSimdReg));
|
||||||
Set("00011111xx0xxxxx0xxxxxxxxxxxxxxx", AInstEmit.Fmadd_S, typeof(AOpCodeSimdReg));
|
Set("00011111xx0xxxxx0xxxxxxxxxxxxxxx", AInstEmit.Fmadd_S, typeof(AOpCodeSimdReg));
|
||||||
Set("00011110xx1xxxxx010010xxxxxxxxxx", AInstEmit.Fmax_S, typeof(AOpCodeSimdReg));
|
Set("00011110xx1xxxxx010010xxxxxxxxxx", AInstEmit.Fmax_S, typeof(AOpCodeSimdReg));
|
||||||
|
@ -186,8 +187,10 @@ namespace ChocolArm64
|
||||||
Set("0x0011101x1xxxxx110101xxxxxxxxxx", AInstEmit.Fsub_V, typeof(AOpCodeSimdReg));
|
Set("0x0011101x1xxxxx110101xxxxxxxxxx", AInstEmit.Fsub_V, typeof(AOpCodeSimdReg));
|
||||||
Set("01001110000xxxxx000111xxxxxxxxxx", AInstEmit.Ins_Gp, typeof(AOpCodeSimdIns));
|
Set("01001110000xxxxx000111xxxxxxxxxx", AInstEmit.Ins_Gp, typeof(AOpCodeSimdIns));
|
||||||
Set("01101110000xxxxx0xxxx1xxxxxxxxxx", AInstEmit.Ins_V, typeof(AOpCodeSimdIns));
|
Set("01101110000xxxxx0xxxx1xxxxxxxxxx", AInstEmit.Ins_V, typeof(AOpCodeSimdIns));
|
||||||
Set("0x00110001000000xxxxxxxxxxxxxxxx", AInstEmit.Ld__V, typeof(AOpCodeSimdMemMult));
|
Set("0x00110001000000xxxxxxxxxxxxxxxx", AInstEmit.Ld__Vms, typeof(AOpCodeSimdMemMs));
|
||||||
Set("0x001100110xxxxxxxxxxxxxxxxxxxxx", AInstEmit.Ld__V, typeof(AOpCodeSimdMemMult));
|
Set("0x001100110xxxxxxxxxxxxxxxxxxxxx", AInstEmit.Ld__Vms, typeof(AOpCodeSimdMemMs));
|
||||||
|
Set("0x00110101000000xx0xxxxxxxxxxxxx", AInstEmit.Ld__Vss, typeof(AOpCodeSimdMemSs));
|
||||||
|
Set("0x001101110xxxxxxx0xxxxxxxxxxxxx", AInstEmit.Ld__Vss, typeof(AOpCodeSimdMemSs));
|
||||||
Set("xx10110xx1xxxxxxxxxxxxxxxxxxxxxx", AInstEmit.Ldp, typeof(AOpCodeSimdMemPair));
|
Set("xx10110xx1xxxxxxxxxxxxxxxxxxxxxx", AInstEmit.Ldp, typeof(AOpCodeSimdMemPair));
|
||||||
Set("xx111100x10xxxxxxxxx00xxxxxxxxxx", AInstEmit.Ldr, typeof(AOpCodeSimdMemImm));
|
Set("xx111100x10xxxxxxxxx00xxxxxxxxxx", AInstEmit.Ldr, typeof(AOpCodeSimdMemImm));
|
||||||
Set("xx111100x10xxxxxxxxx01xxxxxxxxxx", AInstEmit.Ldr, typeof(AOpCodeSimdMemImm));
|
Set("xx111100x10xxxxxxxxx01xxxxxxxxxx", AInstEmit.Ldr, typeof(AOpCodeSimdMemImm));
|
||||||
|
@ -218,8 +221,8 @@ namespace ChocolArm64
|
||||||
Set("0x00111100>>>xxx101001xxxxxxxxxx", AInstEmit.Sshll_V, typeof(AOpCodeSimdShImm));
|
Set("0x00111100>>>xxx101001xxxxxxxxxx", AInstEmit.Sshll_V, typeof(AOpCodeSimdShImm));
|
||||||
Set("010111110>>>>xxx000001xxxxxxxxxx", AInstEmit.Sshr_S, typeof(AOpCodeSimdShImm));
|
Set("010111110>>>>xxx000001xxxxxxxxxx", AInstEmit.Sshr_S, typeof(AOpCodeSimdShImm));
|
||||||
Set("0x0011110>>>>xxx000001xxxxxxxxxx", AInstEmit.Sshr_V, typeof(AOpCodeSimdShImm));
|
Set("0x0011110>>>>xxx000001xxxxxxxxxx", AInstEmit.Sshr_V, typeof(AOpCodeSimdShImm));
|
||||||
Set("0x00110000000000xxxxxxxxxxxxxxxx", AInstEmit.St__V, typeof(AOpCodeSimdMemMult));
|
Set("0x00110000000000xxxxxxxxxxxxxxxx", AInstEmit.St__V, typeof(AOpCodeSimdMemMs));
|
||||||
Set("0x001100100xxxxxxxxxxxxxxxxxxxxx", AInstEmit.St__V, typeof(AOpCodeSimdMemMult));
|
Set("0x001100100xxxxxxxxxxxxxxxxxxxxx", AInstEmit.St__V, typeof(AOpCodeSimdMemMs));
|
||||||
Set("xx10110xx0xxxxxxxxxxxxxxxxxxxxxx", AInstEmit.Stp, typeof(AOpCodeSimdMemPair));
|
Set("xx10110xx0xxxxxxxxxxxxxxxxxxxxxx", AInstEmit.Stp, typeof(AOpCodeSimdMemPair));
|
||||||
Set("xx111100x00xxxxxxxxx00xxxxxxxxxx", AInstEmit.Str, typeof(AOpCodeSimdMemImm));
|
Set("xx111100x00xxxxxxxxx00xxxxxxxxxx", AInstEmit.Str, typeof(AOpCodeSimdMemImm));
|
||||||
Set("xx111100x00xxxxxxxxx01xxxxxxxxxx", AInstEmit.Str, typeof(AOpCodeSimdMemImm));
|
Set("xx111100x00xxxxxxxxx01xxxxxxxxxx", AInstEmit.Str, typeof(AOpCodeSimdMemImm));
|
||||||
|
|
4
Ryujinx/Cpu/AOptimizations.cs
Normal file
4
Ryujinx/Cpu/AOptimizations.cs
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
public static class AOptimizations
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
|
@ -3,7 +3,7 @@ using ChocolArm64.State;
|
||||||
|
|
||||||
namespace ChocolArm64.Decoder
|
namespace ChocolArm64.Decoder
|
||||||
{
|
{
|
||||||
class AOpCodeSimdMemMult : AOpCode, IAOpCodeSimd
|
class AOpCodeSimdMemMs : AOpCode, IAOpCodeSimd
|
||||||
{
|
{
|
||||||
public int Rt { get; private set; }
|
public int Rt { get; private set; }
|
||||||
public int Rn { get; private set; }
|
public int Rn { get; private set; }
|
||||||
|
@ -14,7 +14,7 @@ namespace ChocolArm64.Decoder
|
||||||
public int Elems { get; private set; }
|
public int Elems { get; private set; }
|
||||||
public bool WBack { get; private set; }
|
public bool WBack { get; private set; }
|
||||||
|
|
||||||
public AOpCodeSimdMemMult(AInst Inst, long Position, int OpCode) : base(Inst, Position)
|
public AOpCodeSimdMemMs(AInst Inst, long Position, int OpCode) : base(Inst, Position)
|
||||||
{
|
{
|
||||||
switch ((OpCode >> 12) & 0xf)
|
switch ((OpCode >> 12) & 0xf)
|
||||||
{
|
{
|
104
Ryujinx/Cpu/Decoder/AOpCodeSimdMemSs.cs
Normal file
104
Ryujinx/Cpu/Decoder/AOpCodeSimdMemSs.cs
Normal file
|
@ -0,0 +1,104 @@
|
||||||
|
using ChocolArm64.Instruction;
|
||||||
|
using ChocolArm64.State;
|
||||||
|
|
||||||
|
namespace ChocolArm64.Decoder
|
||||||
|
{
|
||||||
|
class AOpCodeSimdMemSs : AOpCode, IAOpCodeSimd
|
||||||
|
{
|
||||||
|
public int Rt { get; private set; }
|
||||||
|
public int Rn { get; private set; }
|
||||||
|
public int Size { get; private set; }
|
||||||
|
public int Rm { get; private set; }
|
||||||
|
public int SElems { get; private set; }
|
||||||
|
public int Index { get; private set; }
|
||||||
|
public bool Replicate { get; private set; }
|
||||||
|
public bool WBack { get; private set; }
|
||||||
|
|
||||||
|
public AOpCodeSimdMemSs(AInst Inst, long Position, int OpCode) : base(Inst, Position)
|
||||||
|
{
|
||||||
|
int Size = (OpCode >> 10) & 3;
|
||||||
|
int S = (OpCode >> 12) & 1;
|
||||||
|
int SElems = (OpCode >> 12) & 2;
|
||||||
|
int Scale = (OpCode >> 14) & 3;
|
||||||
|
int L = (OpCode >> 22) & 1;
|
||||||
|
int Q = (OpCode >> 30) & 1;
|
||||||
|
|
||||||
|
SElems |= (OpCode >> 21) & 1;
|
||||||
|
|
||||||
|
SElems++;
|
||||||
|
|
||||||
|
int Index = (Q << 3) | (S << 2) | Size;
|
||||||
|
|
||||||
|
switch (Scale)
|
||||||
|
{
|
||||||
|
case 0: Index >>= 0; break;
|
||||||
|
|
||||||
|
case 1:
|
||||||
|
{
|
||||||
|
if ((Index & 1) != 0)
|
||||||
|
{
|
||||||
|
Inst = AInst.Undefined;
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Index >>= 1;
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case 2:
|
||||||
|
{
|
||||||
|
if ((Index & 2) != 0 ||
|
||||||
|
((Index & 1) != 0 && S != 0))
|
||||||
|
{
|
||||||
|
Inst = AInst.Undefined;
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((Index & 1) != 0)
|
||||||
|
{
|
||||||
|
Index >>= 3;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Index >>= 2;
|
||||||
|
|
||||||
|
Scale = 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case 3:
|
||||||
|
{
|
||||||
|
if (L == 0 || S != 0)
|
||||||
|
{
|
||||||
|
Inst = AInst.Undefined;
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Scale = Size;
|
||||||
|
|
||||||
|
Replicate = true;
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
this.SElems = SElems;
|
||||||
|
this.Size = Scale;
|
||||||
|
|
||||||
|
Rt = (OpCode >> 0) & 0x1f;
|
||||||
|
Rn = (OpCode >> 5) & 0x1f;
|
||||||
|
Rm = (OpCode >> 16) & 0x1f;
|
||||||
|
WBack = ((OpCode >> 23) & 0x1) != 0;
|
||||||
|
|
||||||
|
RegisterSize = Q != 0
|
||||||
|
? ARegisterSize.SIMD128
|
||||||
|
: ARegisterSize.SIMD64;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,26 +1,16 @@
|
||||||
using ChocolArm64.Instruction;
|
using ChocolArm64.Instruction;
|
||||||
using ChocolArm64.State;
|
|
||||||
|
|
||||||
namespace ChocolArm64.Decoder
|
namespace ChocolArm64.Decoder
|
||||||
{
|
{
|
||||||
class AOpCodeSimdShImm : AOpCode, IAOpCodeSimd
|
class AOpCodeSimdShImm : AOpCodeSimd
|
||||||
{
|
{
|
||||||
public int Rd { get; private set; }
|
public int Imm { get; private set; }
|
||||||
public int Rn { get; private set; }
|
|
||||||
public int Imm { get; private set; }
|
|
||||||
public int Size { get; private set; }
|
|
||||||
|
|
||||||
public AOpCodeSimdShImm(AInst Inst, long Position, int OpCode) : base(Inst, Position)
|
public AOpCodeSimdShImm(AInst Inst, long Position, int OpCode) : base(Inst, Position, OpCode)
|
||||||
{
|
{
|
||||||
Rd = (OpCode >> 0) & 0x1f;
|
|
||||||
Rn = (OpCode >> 5) & 0x1f;
|
|
||||||
Imm = (OpCode >> 16) & 0x7f;
|
Imm = (OpCode >> 16) & 0x7f;
|
||||||
|
|
||||||
Size = ABitUtils.HighestBitSet32(Imm >> 3);
|
Size = ABitUtils.HighestBitSet32(Imm >> 3);
|
||||||
|
|
||||||
RegisterSize = ((OpCode >> 30) & 1) != 0
|
|
||||||
? ARegisterSize.SIMD128
|
|
||||||
: ARegisterSize.SIMD64;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -102,64 +102,10 @@ namespace ChocolArm64.Instruction
|
||||||
|
|
||||||
public static void Eor_V(AILEmitterCtx Context) => EmitVectorBinaryZx(Context, OpCodes.Xor);
|
public static void Eor_V(AILEmitterCtx Context) => EmitVectorBinaryZx(Context, OpCodes.Xor);
|
||||||
|
|
||||||
public static void Fadd_V(AILEmitterCtx Context)
|
public static void Fadd_V(AILEmitterCtx Context) => EmitVectorBinaryFOp(Context, OpCodes.Add);
|
||||||
{
|
|
||||||
AOpCodeSimdReg Op = (AOpCodeSimdReg)Context.CurrOp;
|
|
||||||
|
|
||||||
Context.EmitLdvec(Op.Rn);
|
public static void Fcvtzs_V(AILEmitterCtx Context) => EmitVectorFcvtS(Context);
|
||||||
Context.EmitLdvec(Op.Rm);
|
public static void Fcvtzu_V(AILEmitterCtx Context) => EmitVectorFcvtU(Context);
|
||||||
Context.EmitLdc_I4(Op.SizeF);
|
|
||||||
|
|
||||||
ASoftFallback.EmitCall(Context,
|
|
||||||
nameof(ASoftFallback.Fadd64),
|
|
||||||
nameof(ASoftFallback.Fadd128));
|
|
||||||
|
|
||||||
Context.EmitStvec(Op.Rd);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void Fcvtzs_V(AILEmitterCtx Context)
|
|
||||||
{
|
|
||||||
AOpCodeSimd Op = (AOpCodeSimd)Context.CurrOp;
|
|
||||||
|
|
||||||
Context.EmitLdvec(Op.Rn);
|
|
||||||
Context.EmitLdc_I4(Op.SizeF);
|
|
||||||
|
|
||||||
ASoftFallback.EmitCall(Context,
|
|
||||||
nameof(ASoftFallback.Fcvtzs_V64),
|
|
||||||
nameof(ASoftFallback.Fcvtzs_V128));
|
|
||||||
|
|
||||||
Context.EmitStvec(Op.Rd);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void Fcvtzu_V(AILEmitterCtx Context)
|
|
||||||
{
|
|
||||||
AOpCodeSimd Op = (AOpCodeSimd)Context.CurrOp;
|
|
||||||
|
|
||||||
Context.EmitLdvec(Op.Rn);
|
|
||||||
Context.EmitLdc_I4(0);
|
|
||||||
Context.EmitLdc_I4(Op.SizeF);
|
|
||||||
|
|
||||||
ASoftFallback.EmitCall(Context,
|
|
||||||
nameof(ASoftFallback.Fcvtzu_V_64),
|
|
||||||
nameof(ASoftFallback.Fcvtzu_V_128));
|
|
||||||
|
|
||||||
Context.EmitStvec(Op.Rd);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void Fcvtzu_V_Fix(AILEmitterCtx Context)
|
|
||||||
{
|
|
||||||
AOpCodeSimdShImm Op = (AOpCodeSimdShImm)Context.CurrOp;
|
|
||||||
|
|
||||||
Context.EmitLdvec(Op.Rn);
|
|
||||||
Context.EmitLdc_I4((8 << (Op.Size + 1)) - Op.Imm);
|
|
||||||
Context.EmitLdc_I4(Op.Size - 2);
|
|
||||||
|
|
||||||
ASoftFallback.EmitCall(Context,
|
|
||||||
nameof(ASoftFallback.Fcvtzu_V_64),
|
|
||||||
nameof(ASoftFallback.Fcvtzu_V_128));
|
|
||||||
|
|
||||||
Context.EmitStvec(Op.Rd);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void Fmla_V(AILEmitterCtx Context)
|
public static void Fmla_V(AILEmitterCtx Context)
|
||||||
{
|
{
|
||||||
|
@ -208,20 +154,7 @@ namespace ChocolArm64.Instruction
|
||||||
Context.EmitStvec(Op.Rd);
|
Context.EmitStvec(Op.Rd);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void Fmul_V(AILEmitterCtx Context)
|
public static void Fmul_V(AILEmitterCtx Context) => EmitVectorBinaryFOp(Context, OpCodes.Mul);
|
||||||
{
|
|
||||||
AOpCodeSimdReg Op = (AOpCodeSimdReg)Context.CurrOp;
|
|
||||||
|
|
||||||
Context.EmitLdvec(Op.Rn);
|
|
||||||
Context.EmitLdvec(Op.Rm);
|
|
||||||
Context.EmitLdc_I4(Op.SizeF);
|
|
||||||
|
|
||||||
ASoftFallback.EmitCall(Context,
|
|
||||||
nameof(ASoftFallback.Fmul64),
|
|
||||||
nameof(ASoftFallback.Fmul128));
|
|
||||||
|
|
||||||
Context.EmitStvec(Op.Rd);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void Fmul_Vs(AILEmitterCtx Context)
|
public static void Fmul_Vs(AILEmitterCtx Context)
|
||||||
{
|
{
|
||||||
|
@ -239,20 +172,7 @@ namespace ChocolArm64.Instruction
|
||||||
Context.EmitStvec(Op.Rd);
|
Context.EmitStvec(Op.Rd);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void Fsub_V(AILEmitterCtx Context)
|
public static void Fsub_V(AILEmitterCtx Context) => EmitVectorBinaryFOp(Context, OpCodes.Sub);
|
||||||
{
|
|
||||||
AOpCodeSimdReg Op = (AOpCodeSimdReg)Context.CurrOp;
|
|
||||||
|
|
||||||
Context.EmitLdvec(Op.Rn);
|
|
||||||
Context.EmitLdvec(Op.Rm);
|
|
||||||
Context.EmitLdc_I4(Op.SizeF);
|
|
||||||
|
|
||||||
ASoftFallback.EmitCall(Context,
|
|
||||||
nameof(ASoftFallback.Fsub64),
|
|
||||||
nameof(ASoftFallback.Fsub128));
|
|
||||||
|
|
||||||
Context.EmitStvec(Op.Rd);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void Ins_Gp(AILEmitterCtx Context)
|
public static void Ins_Gp(AILEmitterCtx Context)
|
||||||
{
|
{
|
||||||
|
@ -283,7 +203,8 @@ namespace ChocolArm64.Instruction
|
||||||
Context.EmitStvec(Op.Rd);
|
Context.EmitStvec(Op.Rd);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void Ld__V(AILEmitterCtx Context) => EmitSimdMultLdSt(Context, IsLoad: true);
|
public static void Ld__Vms(AILEmitterCtx Context) => EmitSimdMemMs(Context, IsLoad: true);
|
||||||
|
public static void Ld__Vss(AILEmitterCtx Context) => EmitSimdMemSs(Context, IsLoad: true);
|
||||||
|
|
||||||
public static void Mla_V(AILEmitterCtx Context) => EmitVectorMla(Context);
|
public static void Mla_V(AILEmitterCtx Context) => EmitVectorMla(Context);
|
||||||
|
|
||||||
|
@ -391,7 +312,7 @@ namespace ChocolArm64.Instruction
|
||||||
EmitVectorImmBinarySx(Context, OpCodes.Shr, (8 << (Op.Size + 1)) - Op.Imm);
|
EmitVectorImmBinarySx(Context, OpCodes.Shr, (8 << (Op.Size + 1)) - Op.Imm);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void St__V(AILEmitterCtx Context) => EmitSimdMultLdSt(Context, IsLoad: false);
|
public static void St__V(AILEmitterCtx Context) => EmitSimdMemMs(Context, IsLoad: false);
|
||||||
|
|
||||||
public static void Sub_V(AILEmitterCtx Context) => EmitVectorBinaryZx(Context, OpCodes.Sub);
|
public static void Sub_V(AILEmitterCtx Context) => EmitVectorBinaryZx(Context, OpCodes.Sub);
|
||||||
|
|
||||||
|
@ -571,9 +492,9 @@ namespace ChocolArm64.Instruction
|
||||||
Context.EmitStvec(Op.Rd);
|
Context.EmitStvec(Op.Rd);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void EmitSimdMultLdSt(AILEmitterCtx Context, bool IsLoad)
|
private static void EmitSimdMemMs(AILEmitterCtx Context, bool IsLoad)
|
||||||
{
|
{
|
||||||
AOpCodeSimdMemMult Op = (AOpCodeSimdMemMult)Context.CurrOp;
|
AOpCodeSimdMemMs Op = (AOpCodeSimdMemMs)Context.CurrOp;
|
||||||
|
|
||||||
int Offset = 0;
|
int Offset = 0;
|
||||||
|
|
||||||
|
@ -644,6 +565,79 @@ namespace ChocolArm64.Instruction
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static void EmitSimdMemSs(AILEmitterCtx Context, bool IsLoad)
|
||||||
|
{
|
||||||
|
AOpCodeSimdMemSs Op = (AOpCodeSimdMemSs)Context.CurrOp;
|
||||||
|
|
||||||
|
//TODO: Replicate mode.
|
||||||
|
|
||||||
|
int Offset = 0;
|
||||||
|
|
||||||
|
for (int SElem = 0; SElem < Op.SElems; SElem++)
|
||||||
|
{
|
||||||
|
int Rt = (Op.Rt + SElem) & 0x1f;
|
||||||
|
|
||||||
|
if (IsLoad)
|
||||||
|
{
|
||||||
|
Context.EmitLdvec(Rt);
|
||||||
|
Context.EmitLdc_I4(Op.Index);
|
||||||
|
Context.EmitLdc_I4(Op.Size);
|
||||||
|
Context.EmitLdarg(ATranslatedSub.MemoryArgIdx);
|
||||||
|
Context.EmitLdint(Op.Rn);
|
||||||
|
Context.EmitLdc_I8(Offset);
|
||||||
|
|
||||||
|
Context.Emit(OpCodes.Add);
|
||||||
|
|
||||||
|
EmitReadZxCall(Context, Op.Size);
|
||||||
|
|
||||||
|
ASoftFallback.EmitCall(Context, nameof(ASoftFallback.InsertVec));
|
||||||
|
|
||||||
|
Context.EmitStvec(Rt);
|
||||||
|
|
||||||
|
if (Op.RegisterSize == ARegisterSize.SIMD64)
|
||||||
|
{
|
||||||
|
EmitVectorZeroUpper(Context, Rt);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Context.EmitLdarg(ATranslatedSub.MemoryArgIdx);
|
||||||
|
Context.EmitLdint(Op.Rn);
|
||||||
|
Context.EmitLdc_I8(Offset);
|
||||||
|
|
||||||
|
Context.Emit(OpCodes.Add);
|
||||||
|
|
||||||
|
Context.EmitLdvec(Rt);
|
||||||
|
Context.EmitLdc_I4(Op.Index);
|
||||||
|
Context.EmitLdc_I4(Op.Size);
|
||||||
|
|
||||||
|
ASoftFallback.EmitCall(Context, nameof(ASoftFallback.ExtractVec));
|
||||||
|
|
||||||
|
EmitWriteCall(Context, Op.Size);
|
||||||
|
}
|
||||||
|
|
||||||
|
Offset += 1 << Op.Size;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Op.WBack)
|
||||||
|
{
|
||||||
|
Context.EmitLdint(Op.Rn);
|
||||||
|
|
||||||
|
if (Op.Rm != ARegisters.ZRIndex)
|
||||||
|
{
|
||||||
|
Context.EmitLdint(Op.Rm);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Context.EmitLdc_I8(Offset);
|
||||||
|
}
|
||||||
|
|
||||||
|
Context.Emit(OpCodes.Add);
|
||||||
|
|
||||||
|
Context.EmitStint(Op.Rn);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private static void EmitVectorAddv(AILEmitterCtx Context)
|
private static void EmitVectorAddv(AILEmitterCtx Context)
|
||||||
{
|
{
|
||||||
AOpCodeSimd Op = (AOpCodeSimd)Context.CurrOp;
|
AOpCodeSimd Op = (AOpCodeSimd)Context.CurrOp;
|
||||||
|
@ -780,6 +774,114 @@ namespace ChocolArm64.Instruction
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static void EmitVectorFcvtS(AILEmitterCtx Context)
|
||||||
|
{
|
||||||
|
EmitVectorCvtOp(Context, CvtDir.Fcvt, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void EmitVectorFcvtU(AILEmitterCtx Context)
|
||||||
|
{
|
||||||
|
EmitVectorCvtOp(Context, CvtDir.Fcvt, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void EmitVectorCvtfS(AILEmitterCtx Context)
|
||||||
|
{
|
||||||
|
EmitVectorCvtOp(Context, CvtDir.Cvtf, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void EmitVectorCvtfU(AILEmitterCtx Context)
|
||||||
|
{
|
||||||
|
EmitVectorCvtOp(Context, CvtDir.Cvtf, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
private enum CvtDir
|
||||||
|
{
|
||||||
|
Fcvt,
|
||||||
|
Cvtf
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void EmitVectorCvtOp(AILEmitterCtx Context, CvtDir Dir, bool Signed)
|
||||||
|
{
|
||||||
|
AOpCodeSimd Op = (AOpCodeSimd)Context.CurrOp;
|
||||||
|
|
||||||
|
int SizeF = Op.Size & 1;
|
||||||
|
int SizeI = SizeF + 2;
|
||||||
|
|
||||||
|
int FBits = 0;
|
||||||
|
|
||||||
|
if (Op is AOpCodeSimdShImm OpImm)
|
||||||
|
{
|
||||||
|
FBits = (8 << (Op.Size + 1)) - OpImm.Imm;
|
||||||
|
}
|
||||||
|
|
||||||
|
int Bytes = Context.CurrOp.GetBitsCount() >> 3;
|
||||||
|
|
||||||
|
for (int Index = 0; Index < (Bytes >> SizeI); Index++)
|
||||||
|
{
|
||||||
|
EmitVectorExtractF(Context, Op.Rn, Index, SizeF);
|
||||||
|
|
||||||
|
Context.EmitLdc_I4(FBits);
|
||||||
|
|
||||||
|
if (Dir == CvtDir.Fcvt)
|
||||||
|
{
|
||||||
|
//Float to Integer.
|
||||||
|
if (SizeF == 0)
|
||||||
|
{
|
||||||
|
ASoftFallback.EmitCall(Context, Signed
|
||||||
|
? nameof(ASoftFallback.SatSingleToInt32)
|
||||||
|
: nameof(ASoftFallback.SatSingleToUInt32));
|
||||||
|
}
|
||||||
|
else if (SizeF == 1)
|
||||||
|
{
|
||||||
|
ASoftFallback.EmitCall(Context, Signed
|
||||||
|
? nameof(ASoftFallback.SatDoubleToInt64)
|
||||||
|
: nameof(ASoftFallback.SatDoubleToUInt64));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (Dir == CvtDir.Cvtf)
|
||||||
|
{
|
||||||
|
//Integer to Float.
|
||||||
|
//TODO.
|
||||||
|
}
|
||||||
|
|
||||||
|
EmitVectorInsert(Context, Op.Rd, Index, SizeI);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Op.RegisterSize == ARegisterSize.SIMD64)
|
||||||
|
{
|
||||||
|
EmitVectorZeroUpper(Context, Op.Rd);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void EmitVectorBinaryFOp(AILEmitterCtx Context, OpCode ILOp)
|
||||||
|
{
|
||||||
|
EmitVectorBinaryFOp(Context, () => Context.Emit(ILOp));
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void EmitVectorBinaryFOp(AILEmitterCtx Context, Action Emit)
|
||||||
|
{
|
||||||
|
AOpCodeSimdReg Op = (AOpCodeSimdReg)Context.CurrOp;
|
||||||
|
|
||||||
|
int SizeF = Op.Size & 1;
|
||||||
|
|
||||||
|
int Bytes = Context.CurrOp.GetBitsCount() >> 3;
|
||||||
|
|
||||||
|
for (int Index = 0; Index < (Bytes >> SizeF + 2); Index++)
|
||||||
|
{
|
||||||
|
EmitVectorExtractF(Context, Op.Rn, Index, SizeF);
|
||||||
|
EmitVectorExtractF(Context, Op.Rm, Index, SizeF);
|
||||||
|
|
||||||
|
Emit();
|
||||||
|
|
||||||
|
EmitVectorInsertF(Context, Op.Rd, Index, SizeF);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Op.RegisterSize == ARegisterSize.SIMD64)
|
||||||
|
{
|
||||||
|
EmitVectorZeroUpper(Context, Op.Rd);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private static void EmitVectorUnarySx(AILEmitterCtx Context, OpCode ILOp)
|
private static void EmitVectorUnarySx(AILEmitterCtx Context, OpCode ILOp)
|
||||||
{
|
{
|
||||||
EmitVectorUnarySx(Context, () => Context.Emit(ILOp));
|
EmitVectorUnarySx(Context, () => Context.Emit(ILOp));
|
||||||
|
@ -957,6 +1059,25 @@ namespace ChocolArm64.Instruction
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static void EmitVectorExtractF(AILEmitterCtx Context, int Reg, int Index, int Size)
|
||||||
|
{
|
||||||
|
Context.EmitLdvec(Reg);
|
||||||
|
Context.EmitLdc_I4(Index);
|
||||||
|
|
||||||
|
if (Size == 0)
|
||||||
|
{
|
||||||
|
ASoftFallback.EmitCall(Context, nameof(ASoftFallback.VectorExtractSingle));
|
||||||
|
}
|
||||||
|
else if (Size == 1)
|
||||||
|
{
|
||||||
|
ASoftFallback.EmitCall(Context, nameof(ASoftFallback.VectorExtractDouble));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
throw new ArgumentOutOfRangeException(nameof(Size));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private static void EmitVectorExtractSx(AILEmitterCtx Context, int Reg, int Index)
|
private static void EmitVectorExtractSx(AILEmitterCtx Context, int Reg, int Index)
|
||||||
{
|
{
|
||||||
EmitVectorExtract(Context, Reg, Index, true);
|
EmitVectorExtract(Context, Reg, Index, true);
|
||||||
|
@ -980,6 +1101,27 @@ namespace ChocolArm64.Instruction
|
||||||
: nameof(ASoftFallback.ExtractVec));
|
: nameof(ASoftFallback.ExtractVec));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static void EmitVectorInsertF(AILEmitterCtx Context, int Reg, int Index, int Size)
|
||||||
|
{
|
||||||
|
Context.EmitLdvec(Reg);
|
||||||
|
Context.EmitLdc_I4(Index);
|
||||||
|
|
||||||
|
if (Size == 0)
|
||||||
|
{
|
||||||
|
ASoftFallback.EmitCall(Context, nameof(ASoftFallback.VectorInsertSingle));
|
||||||
|
}
|
||||||
|
else if (Size == 1)
|
||||||
|
{
|
||||||
|
ASoftFallback.EmitCall(Context, nameof(ASoftFallback.VectorInsertDouble));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
throw new ArgumentOutOfRangeException(nameof(Size));
|
||||||
|
}
|
||||||
|
|
||||||
|
Context.EmitStvec(Reg);
|
||||||
|
}
|
||||||
|
|
||||||
private static void EmitVectorZeroLower(AILEmitterCtx Context, int Rd)
|
private static void EmitVectorZeroLower(AILEmitterCtx Context, int Rd)
|
||||||
{
|
{
|
||||||
EmitVectorInsert(Context, Rd, 0, 3, 0);
|
EmitVectorInsert(Context, Rd, 0, 3, 0);
|
||||||
|
@ -990,6 +1132,17 @@ namespace ChocolArm64.Instruction
|
||||||
EmitVectorInsert(Context, Rd, 1, 3, 0);
|
EmitVectorInsert(Context, Rd, 1, 3, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static void EmitVectorInsert(AILEmitterCtx Context, int Reg, int Index, int Size)
|
||||||
|
{
|
||||||
|
Context.EmitLdvec(Reg);
|
||||||
|
Context.EmitLdc_I4(Index);
|
||||||
|
Context.EmitLdc_I4(Size);
|
||||||
|
|
||||||
|
ASoftFallback.EmitCall(Context, nameof(ASoftFallback.VectorInsertInt));
|
||||||
|
|
||||||
|
Context.EmitStvec(Reg);
|
||||||
|
}
|
||||||
|
|
||||||
private static void EmitVectorInsert(AILEmitterCtx Context, int Reg, int Index, int Size, long Value)
|
private static void EmitVectorInsert(AILEmitterCtx Context, int Reg, int Index, int Size, long Value)
|
||||||
{
|
{
|
||||||
Context.EmitLdvec(Reg);
|
Context.EmitLdvec(Reg);
|
||||||
|
|
|
@ -365,122 +365,6 @@ namespace ChocolArm64.Instruction
|
||||||
return Res;
|
return Res;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static AVec Fadd64(AVec LHS, AVec RHS, int Size)
|
|
||||||
{
|
|
||||||
return Fadd(LHS, RHS, Size, 2);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static AVec Fadd128(AVec LHS, AVec RHS, int Size)
|
|
||||||
{
|
|
||||||
return Fadd(LHS, RHS, Size, 4);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static AVec Fadd(AVec LHS, AVec RHS, int Size, int Bytes)
|
|
||||||
{
|
|
||||||
AVec Res = new AVec();
|
|
||||||
|
|
||||||
int Elems = Bytes >> Size;
|
|
||||||
|
|
||||||
if (Size == 0)
|
|
||||||
{
|
|
||||||
for (int Index = 0; Index < Elems; Index++)
|
|
||||||
{
|
|
||||||
float L = LHS.ExtractSingle(Index);
|
|
||||||
float R = RHS.ExtractSingle(Index);
|
|
||||||
|
|
||||||
Res = AVec.InsertSingle(Res, Index, L + R);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
for (int Index = 0; Index < Elems; Index++)
|
|
||||||
{
|
|
||||||
double L = LHS.ExtractDouble(Index);
|
|
||||||
double R = RHS.ExtractDouble(Index);
|
|
||||||
|
|
||||||
Res = AVec.InsertDouble(Res, Index, L + R);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return Res;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static AVec Fcvtzs_V64(AVec Vector, int Size)
|
|
||||||
{
|
|
||||||
return Fcvtzs_V(Vector, Size, 2);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static AVec Fcvtzs_V128(AVec Vector, int Size)
|
|
||||||
{
|
|
||||||
return Fcvtzs_V(Vector, Size, 4);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static AVec Fcvtzs_V(AVec Vector, int Size, int Bytes)
|
|
||||||
{
|
|
||||||
AVec Res = new AVec();
|
|
||||||
|
|
||||||
int Elems = Bytes >> Size;
|
|
||||||
|
|
||||||
if (Size == 0)
|
|
||||||
{
|
|
||||||
for (int Index = 0; Index < Elems; Index++)
|
|
||||||
{
|
|
||||||
float Value = Vector.ExtractSingle(Index);
|
|
||||||
|
|
||||||
Res = InsertSVec(Res, Index, Size + 2, SatSingleToInt32(Value));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
for (int Index = 0; Index < Elems; Index++)
|
|
||||||
{
|
|
||||||
double Value = Vector.ExtractDouble(Index);
|
|
||||||
|
|
||||||
Res = InsertSVec(Res, Index, Size + 2, SatDoubleToInt64(Value));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return Res;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static AVec Fcvtzu_V_64(AVec Vector, int FBits, int Size)
|
|
||||||
{
|
|
||||||
return Fcvtzu_V(Vector, FBits, Size, 2);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static AVec Fcvtzu_V_128(AVec Vector, int FBits, int Size)
|
|
||||||
{
|
|
||||||
return Fcvtzu_V(Vector, FBits, Size, 4);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static AVec Fcvtzu_V(AVec Vector, int FBits, int Size, int Bytes)
|
|
||||||
{
|
|
||||||
AVec Res = new AVec();
|
|
||||||
|
|
||||||
int Elems = Bytes >> Size;
|
|
||||||
|
|
||||||
if (Size == 0)
|
|
||||||
{
|
|
||||||
for (int Index = 0; Index < Elems; Index++)
|
|
||||||
{
|
|
||||||
float Value = Vector.ExtractSingle(Index);
|
|
||||||
|
|
||||||
Res = InsertVec(Res, Index, Size + 2, SatSingleToUInt32(Value, FBits));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
for (int Index = 0; Index < Elems; Index++)
|
|
||||||
{
|
|
||||||
double Value = Vector.ExtractDouble(Index);
|
|
||||||
|
|
||||||
Res = InsertVec(Res, Index, Size + 2, SatDoubleToUInt64(Value, FBits));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return Res;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static AVec Fmla64(AVec Res, AVec LHS, AVec RHS, int Size)
|
public static AVec Fmla64(AVec Res, AVec LHS, AVec RHS, int Size)
|
||||||
{
|
{
|
||||||
return Fmla(Res, LHS, RHS, Size, 2);
|
return Fmla(Res, LHS, RHS, Size, 2);
|
||||||
|
@ -568,46 +452,6 @@ namespace ChocolArm64.Instruction
|
||||||
return InsertVec(new AVec(), Elem, Size, Value);
|
return InsertVec(new AVec(), Elem, Size, Value);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static AVec Fmul64(AVec LHS, AVec RHS, int Size)
|
|
||||||
{
|
|
||||||
return Fmul(LHS, RHS, Size, 2);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static AVec Fmul128(AVec LHS, AVec RHS, int Size)
|
|
||||||
{
|
|
||||||
return Fmul(LHS, RHS, Size, 4);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static AVec Fmul(AVec LHS, AVec RHS, int Size, int Bytes)
|
|
||||||
{
|
|
||||||
AVec Res = new AVec();
|
|
||||||
|
|
||||||
int Elems = Bytes >> Size;
|
|
||||||
|
|
||||||
if (Size == 0)
|
|
||||||
{
|
|
||||||
for (int Index = 0; Index < Elems; Index++)
|
|
||||||
{
|
|
||||||
float L = LHS.ExtractSingle(Index);
|
|
||||||
float R = RHS.ExtractSingle(Index);
|
|
||||||
|
|
||||||
Res = AVec.InsertSingle(Res, Index, L * R);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
for (int Index = 0; Index < Elems; Index++)
|
|
||||||
{
|
|
||||||
double L = LHS.ExtractDouble(Index);
|
|
||||||
double R = RHS.ExtractDouble(Index);
|
|
||||||
|
|
||||||
Res = AVec.InsertDouble(Res, Index, L * R);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return Res;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static AVec Fmul_Ve64(AVec LHS, AVec RHS, int SIdx, int Size)
|
public static AVec Fmul_Ve64(AVec LHS, AVec RHS, int SIdx, int Size)
|
||||||
{
|
{
|
||||||
return Fmul_Ve(LHS, RHS, SIdx, Size, 2);
|
return Fmul_Ve(LHS, RHS, SIdx, Size, 2);
|
||||||
|
@ -650,46 +494,6 @@ namespace ChocolArm64.Instruction
|
||||||
return Res;
|
return Res;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static AVec Fsub64(AVec LHS, AVec RHS, int Size)
|
|
||||||
{
|
|
||||||
return Fsub(LHS, RHS, Size, 2);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static AVec Fsub128(AVec LHS, AVec RHS, int Size)
|
|
||||||
{
|
|
||||||
return Fsub(LHS, RHS, Size, 4);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static AVec Fsub(AVec LHS, AVec RHS, int Size, int Bytes)
|
|
||||||
{
|
|
||||||
AVec Res = new AVec();
|
|
||||||
|
|
||||||
int Elems = Bytes >> Size;
|
|
||||||
|
|
||||||
if (Size == 0)
|
|
||||||
{
|
|
||||||
for (int Index = 0; Index < Elems; Index++)
|
|
||||||
{
|
|
||||||
float L = LHS.ExtractSingle(Index);
|
|
||||||
float R = RHS.ExtractSingle(Index);
|
|
||||||
|
|
||||||
Res = AVec.InsertSingle(Res, Index, L - R);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
for (int Index = 0; Index < Elems; Index++)
|
|
||||||
{
|
|
||||||
double L = LHS.ExtractDouble(Index);
|
|
||||||
double R = RHS.ExtractDouble(Index);
|
|
||||||
|
|
||||||
Res = AVec.InsertDouble(Res, Index, L - R);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return Res;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static AVec Ins_Gp(AVec Res, ulong Value, int Elem, int Size)
|
public static AVec Ins_Gp(AVec Res, ulong Value, int Elem, int Size)
|
||||||
{
|
{
|
||||||
return InsertVec(Res, Elem, Size, Value);
|
return InsertVec(Res, Elem, Size, Value);
|
||||||
|
@ -1126,6 +930,39 @@ namespace ChocolArm64.Instruction
|
||||||
throw new ArgumentOutOfRangeException(nameof(Size));
|
throw new ArgumentOutOfRangeException(nameof(Size));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static float VectorExtractSingle(AVec Vector, int Index)
|
||||||
|
{
|
||||||
|
return Vector.ExtractSingle(Index);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static double VectorExtractDouble(AVec Vector, int Index)
|
||||||
|
{
|
||||||
|
return Vector.ExtractDouble(Index);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static AVec VectorInsertSingle(float Value, AVec Vector, int Index)
|
||||||
|
{
|
||||||
|
return AVec.InsertSingle(Vector, Index, Value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static AVec VectorInsertDouble(double Value, AVec Vector, int Index)
|
||||||
|
{
|
||||||
|
return AVec.InsertDouble(Vector, Index, Value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static AVec VectorInsertInt(ulong Value, AVec Vector, int Index, int Size)
|
||||||
|
{
|
||||||
|
switch (Size)
|
||||||
|
{
|
||||||
|
case 0: return AVec.InsertByte (Vector, Index, (byte)Value);
|
||||||
|
case 1: return AVec.InsertUInt16(Vector, Index, (ushort)Value);
|
||||||
|
case 2: return AVec.InsertUInt32(Vector, Index, (uint)Value);
|
||||||
|
case 3: return AVec.InsertUInt64(Vector, Index, (ulong)Value);
|
||||||
|
}
|
||||||
|
|
||||||
|
throw new ArgumentOutOfRangeException(nameof(Size));
|
||||||
|
}
|
||||||
|
|
||||||
public static AVec InsertVec(AVec Vector, int Index, int Size, ulong Value)
|
public static AVec InsertVec(AVec Vector, int Index, int Size, ulong Value)
|
||||||
{
|
{
|
||||||
switch (Size)
|
switch (Size)
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
using ChocolArm64.Exceptions;
|
||||||
using ChocolArm64.State;
|
using ChocolArm64.State;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
@ -119,26 +120,46 @@ namespace ChocolArm64.Memory
|
||||||
|
|
||||||
public byte ReadByte(long Position)
|
public byte ReadByte(long Position)
|
||||||
{
|
{
|
||||||
|
#if DEBUG
|
||||||
|
EnsureAccessIsValid(Position, AMemoryPerm.Read);
|
||||||
|
#endif
|
||||||
|
|
||||||
return *((byte*)(RamPtr + (uint)Position));
|
return *((byte*)(RamPtr + (uint)Position));
|
||||||
}
|
}
|
||||||
|
|
||||||
public ushort ReadUInt16(long Position)
|
public ushort ReadUInt16(long Position)
|
||||||
{
|
{
|
||||||
|
#if DEBUG
|
||||||
|
EnsureAccessIsValid(Position, AMemoryPerm.Read);
|
||||||
|
#endif
|
||||||
|
|
||||||
return *((ushort*)(RamPtr + (uint)Position));
|
return *((ushort*)(RamPtr + (uint)Position));
|
||||||
}
|
}
|
||||||
|
|
||||||
public uint ReadUInt32(long Position)
|
public uint ReadUInt32(long Position)
|
||||||
{
|
{
|
||||||
|
#if DEBUG
|
||||||
|
EnsureAccessIsValid(Position, AMemoryPerm.Read);
|
||||||
|
#endif
|
||||||
|
|
||||||
return *((uint*)(RamPtr + (uint)Position));
|
return *((uint*)(RamPtr + (uint)Position));
|
||||||
}
|
}
|
||||||
|
|
||||||
public ulong ReadUInt64(long Position)
|
public ulong ReadUInt64(long Position)
|
||||||
{
|
{
|
||||||
|
#if DEBUG
|
||||||
|
EnsureAccessIsValid(Position, AMemoryPerm.Read);
|
||||||
|
#endif
|
||||||
|
|
||||||
return *((ulong*)(RamPtr + (uint)Position));
|
return *((ulong*)(RamPtr + (uint)Position));
|
||||||
}
|
}
|
||||||
|
|
||||||
public AVec ReadVector128(long Position)
|
public AVec ReadVector128(long Position)
|
||||||
{
|
{
|
||||||
|
#if DEBUG
|
||||||
|
EnsureAccessIsValid(Position, AMemoryPerm.Read);
|
||||||
|
#endif
|
||||||
|
|
||||||
return new AVec()
|
return new AVec()
|
||||||
{
|
{
|
||||||
X0 = ReadUInt64(Position + 0),
|
X0 = ReadUInt64(Position + 0),
|
||||||
|
@ -153,33 +174,61 @@ namespace ChocolArm64.Memory
|
||||||
|
|
||||||
public void WriteByte(long Position, byte Value)
|
public void WriteByte(long Position, byte Value)
|
||||||
{
|
{
|
||||||
|
#if DEBUG
|
||||||
|
EnsureAccessIsValid(Position, AMemoryPerm.Write);
|
||||||
|
#endif
|
||||||
|
|
||||||
*((byte*)(RamPtr + (uint)Position)) = Value;
|
*((byte*)(RamPtr + (uint)Position)) = Value;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void WriteUInt16(long Position, ushort Value)
|
public void WriteUInt16(long Position, ushort Value)
|
||||||
{
|
{
|
||||||
|
#if DEBUG
|
||||||
|
EnsureAccessIsValid(Position, AMemoryPerm.Write);
|
||||||
|
#endif
|
||||||
|
|
||||||
*((ushort*)(RamPtr + (uint)Position)) = Value;
|
*((ushort*)(RamPtr + (uint)Position)) = Value;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void WriteUInt32(long Position, uint Value)
|
public void WriteUInt32(long Position, uint Value)
|
||||||
{
|
{
|
||||||
|
#if DEBUG
|
||||||
|
EnsureAccessIsValid(Position, AMemoryPerm.Write);
|
||||||
|
#endif
|
||||||
|
|
||||||
*((uint*)(RamPtr + (uint)Position)) = Value;
|
*((uint*)(RamPtr + (uint)Position)) = Value;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void WriteUInt64(long Position, ulong Value)
|
public void WriteUInt64(long Position, ulong Value)
|
||||||
{
|
{
|
||||||
|
#if DEBUG
|
||||||
|
EnsureAccessIsValid(Position, AMemoryPerm.Write);
|
||||||
|
#endif
|
||||||
|
|
||||||
*((ulong*)(RamPtr + (uint)Position)) = Value;
|
*((ulong*)(RamPtr + (uint)Position)) = Value;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void WriteVector128(long Position, AVec Value)
|
public void WriteVector128(long Position, AVec Value)
|
||||||
{
|
{
|
||||||
|
#if DEBUG
|
||||||
|
EnsureAccessIsValid(Position, AMemoryPerm.Write);
|
||||||
|
#endif
|
||||||
|
|
||||||
WriteUInt64(Position + 0, Value.X0);
|
WriteUInt64(Position + 0, Value.X0);
|
||||||
WriteUInt64(Position + 8, Value.X1);
|
WriteUInt64(Position + 8, Value.X1);
|
||||||
}
|
}
|
||||||
|
|
||||||
private bool IsPageCrossed(long Position, int Size)
|
private void EnsureAccessIsValid(long Position, AMemoryPerm Perm)
|
||||||
{
|
{
|
||||||
return (Position & AMemoryMgr.PageMask) + Size > AMemoryMgr.PageSize;
|
if (!Manager.IsMapped(Position))
|
||||||
|
{
|
||||||
|
throw new VmmPageFaultException(Position);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!Manager.HasPermission(Position, Perm))
|
||||||
|
{
|
||||||
|
throw new VmmAccessViolationException(Position, Perm);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -1,5 +1,3 @@
|
||||||
using ChocolArm64.Exceptions;
|
|
||||||
using System;
|
|
||||||
using System.Runtime.CompilerServices;
|
using System.Runtime.CompilerServices;
|
||||||
|
|
||||||
namespace ChocolArm64.Memory
|
namespace ChocolArm64.Memory
|
||||||
|
@ -163,7 +161,7 @@ namespace ChocolArm64.Memory
|
||||||
{
|
{
|
||||||
while (Size > 0)
|
while (Size > 0)
|
||||||
{
|
{
|
||||||
if (!HasPTEntry(Position))
|
if (!IsMapped(Position))
|
||||||
{
|
{
|
||||||
long PhysPos = Allocator.Alloc(PageSize);
|
long PhysPos = Allocator.Alloc(PageSize);
|
||||||
|
|
||||||
|
@ -254,8 +252,13 @@ namespace ChocolArm64.Memory
|
||||||
return new AMemoryMapInfo(Start, Size, BaseEntry.Type, BaseEntry.Perm);
|
return new AMemoryMapInfo(Start, Size, BaseEntry.Type, BaseEntry.Perm);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public bool HasPermission(long Position, AMemoryPerm Perm)
|
||||||
|
{
|
||||||
|
return GetPTEntry(Position).Perm.HasFlag(Perm);
|
||||||
|
}
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
private bool HasPTEntry(long Position)
|
public bool IsMapped(long Position)
|
||||||
{
|
{
|
||||||
if (Position >> PTLvl0Bits + PTLvl1Bits + PTPageBits != 0)
|
if (Position >> PTLvl0Bits + PTLvl1Bits + PTPageBits != 0)
|
||||||
{
|
{
|
||||||
|
|
|
@ -73,12 +73,14 @@ namespace Ryujinx.Loaders
|
||||||
MemoryType Type,
|
MemoryType Type,
|
||||||
AMemoryPerm Perm)
|
AMemoryPerm Perm)
|
||||||
{
|
{
|
||||||
Memory.Manager.MapPhys(Position, Data.Count, (int)Type, Perm);
|
Memory.Manager.MapPhys(Position, Data.Count, (int)Type, AMemoryPerm.Write);
|
||||||
|
|
||||||
for (int Index = 0; Index < Data.Count; Index++)
|
for (int Index = 0; Index < Data.Count; Index++)
|
||||||
{
|
{
|
||||||
Memory.WriteByte(Position + Index, Data[Index]);
|
Memory.WriteByte(Position + Index, Data[Index]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Memory.Manager.Reprotect(Position, Data.Count, Perm);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void MapBss(long Position, long Size)
|
private void MapBss(long Position, long Size)
|
||||||
|
|
132
Ryujinx/Logging.cs
Normal file
132
Ryujinx/Logging.cs
Normal file
|
@ -0,0 +1,132 @@
|
||||||
|
using System;
|
||||||
|
using System.Diagnostics;
|
||||||
|
using System.IO;
|
||||||
|
|
||||||
|
namespace Ryujinx
|
||||||
|
{
|
||||||
|
public static class Logging
|
||||||
|
{
|
||||||
|
private static Stopwatch ExecutionTime = new Stopwatch();
|
||||||
|
private static string LogFileName = "Ryujinx.log";
|
||||||
|
|
||||||
|
public static bool EnableInfo = Config.LoggingEnableInfo;
|
||||||
|
public static bool EnableTrace = Config.LoggingEnableTrace;
|
||||||
|
public static bool EnableDebug = Config.LoggingEnableDebug;
|
||||||
|
public static bool EnableWarn = Config.LoggingEnableWarn;
|
||||||
|
public static bool EnableError = Config.LoggingEnableError;
|
||||||
|
public static bool EnableFatal = Config.LoggingEnableFatal;
|
||||||
|
public static bool EnableLogFile = Config.LoggingEnableLogFile;
|
||||||
|
|
||||||
|
static Logging()
|
||||||
|
{
|
||||||
|
ExecutionTime.Start();
|
||||||
|
|
||||||
|
if (File.Exists(LogFileName)) File.Delete(LogFileName);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static string GetExecutionTime()
|
||||||
|
{
|
||||||
|
return ExecutionTime.ElapsedMilliseconds.ToString().PadLeft(8, '0') + "ms";
|
||||||
|
}
|
||||||
|
|
||||||
|
private static string WhoCalledMe()
|
||||||
|
{
|
||||||
|
return new StackTrace().GetFrame(2).GetMethod().Name;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void LogFile(string Message)
|
||||||
|
{
|
||||||
|
if (EnableLogFile)
|
||||||
|
{
|
||||||
|
using (StreamWriter Writer = File.AppendText(LogFileName))
|
||||||
|
{
|
||||||
|
Writer.WriteLine(Message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void Info(string Message)
|
||||||
|
{
|
||||||
|
if (EnableInfo)
|
||||||
|
{
|
||||||
|
string Text = $"{GetExecutionTime()} | INFO > {Message}";
|
||||||
|
|
||||||
|
Console.ForegroundColor = ConsoleColor.White;
|
||||||
|
Console.WriteLine(Text.PadLeft(Text.Length + 1, ' '));
|
||||||
|
Console.ResetColor();
|
||||||
|
|
||||||
|
LogFile(Text);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void Trace(string Message)
|
||||||
|
{
|
||||||
|
if (EnableTrace)
|
||||||
|
{
|
||||||
|
string Text = $"{GetExecutionTime()} | TRACE > {WhoCalledMe()} - {Message}";
|
||||||
|
|
||||||
|
Console.ForegroundColor = ConsoleColor.DarkGray;
|
||||||
|
Console.WriteLine(Text.PadLeft(Text.Length + 1, ' '));
|
||||||
|
Console.ResetColor();
|
||||||
|
|
||||||
|
LogFile(Text);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void Debug(string Message)
|
||||||
|
{
|
||||||
|
if (EnableDebug)
|
||||||
|
{
|
||||||
|
string Text = $"{GetExecutionTime()} | DEBUG > {WhoCalledMe()} - {Message}";
|
||||||
|
|
||||||
|
Console.ForegroundColor = ConsoleColor.Gray;
|
||||||
|
Console.WriteLine(Text.PadLeft(Text.Length + 1, ' '));
|
||||||
|
Console.ResetColor();
|
||||||
|
|
||||||
|
LogFile(Text);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void Warn(string Message)
|
||||||
|
{
|
||||||
|
if (EnableWarn)
|
||||||
|
{
|
||||||
|
string Text = $"{GetExecutionTime()} | WARN > {WhoCalledMe()} - {Message}";
|
||||||
|
|
||||||
|
Console.ForegroundColor = ConsoleColor.Yellow;
|
||||||
|
Console.WriteLine(Text.PadLeft(Text.Length + 1, ' '));
|
||||||
|
Console.ResetColor();
|
||||||
|
|
||||||
|
LogFile(Text);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void Error(string Message)
|
||||||
|
{
|
||||||
|
if (EnableError)
|
||||||
|
{
|
||||||
|
string Text = $"{GetExecutionTime()} | ERROR > {WhoCalledMe()} - {Message}";
|
||||||
|
|
||||||
|
Console.ForegroundColor = ConsoleColor.Red;
|
||||||
|
Console.WriteLine(Text.PadLeft(Text.Length + 1, ' '));
|
||||||
|
Console.ResetColor();
|
||||||
|
|
||||||
|
LogFile(Text);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void Fatal(string Message)
|
||||||
|
{
|
||||||
|
if (EnableFatal)
|
||||||
|
{
|
||||||
|
string Text = $"{GetExecutionTime()} | FATAL > {WhoCalledMe()} - {Message}";
|
||||||
|
|
||||||
|
Console.ForegroundColor = ConsoleColor.Magenta;
|
||||||
|
Console.WriteLine(Text.PadLeft(Text.Length + 1, ' '));
|
||||||
|
Console.ResetColor();
|
||||||
|
|
||||||
|
LogFile(Text);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -262,6 +262,8 @@ namespace Ryujinx.OsHle.Ipc
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Logging.Debug($"IpcMessage: {DbgServiceName}");
|
||||||
|
|
||||||
if (ProcReq != null)
|
if (ProcReq != null)
|
||||||
{
|
{
|
||||||
using (MemoryStream ResMS = new MemoryStream())
|
using (MemoryStream ResMS = new MemoryStream())
|
||||||
|
|
|
@ -1,15 +1,12 @@
|
||||||
using ChocolArm64.Memory;
|
using ChocolArm64.Memory;
|
||||||
|
using OpenTK.Audio;
|
||||||
|
using OpenTK.Audio.OpenAL;
|
||||||
using Ryujinx.OsHle.Handles;
|
using Ryujinx.OsHle.Handles;
|
||||||
using Ryujinx.OsHle.Ipc;
|
using Ryujinx.OsHle.Ipc;
|
||||||
using static Ryujinx.OsHle.Objects.ObjHelper;
|
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
|
|
||||||
using OpenTK.Audio;
|
|
||||||
using OpenTK.Audio.OpenAL;
|
|
||||||
|
|
||||||
namespace Ryujinx.OsHle.Objects
|
namespace Ryujinx.OsHle.Objects
|
||||||
{
|
{
|
||||||
class AudIAudioOut
|
class AudIAudioOut
|
||||||
|
@ -22,7 +19,7 @@ namespace Ryujinx.OsHle.Objects
|
||||||
|
|
||||||
//IAudioOut
|
//IAudioOut
|
||||||
private static AudioOutState State = AudioOutState.Stopped;
|
private static AudioOutState State = AudioOutState.Stopped;
|
||||||
private static List<long> KeysQueue = new List<long>();
|
private static Queue<long> KeysQueue = new Queue<long>();
|
||||||
|
|
||||||
//OpenAL
|
//OpenAL
|
||||||
private static bool OpenALInstalled = true;
|
private static bool OpenALInstalled = true;
|
||||||
|
@ -48,9 +45,9 @@ namespace Ryujinx.OsHle.Objects
|
||||||
{
|
{
|
||||||
AudioCtx = new AudioContext(); //Create the audio context
|
AudioCtx = new AudioContext(); //Create the audio context
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception)
|
||||||
{
|
{
|
||||||
Console.WriteLine("OpenAL Error! PS: Install OpenAL Core SDK!");
|
Logging.Warn("OpenAL Error! PS: Install OpenAL Core SDK!");
|
||||||
OpenALInstalled = false;
|
OpenALInstalled = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -82,7 +79,7 @@ namespace Ryujinx.OsHle.Objects
|
||||||
{
|
{
|
||||||
long BufferId = Context.RequestData.ReadInt64();
|
long BufferId = Context.RequestData.ReadInt64();
|
||||||
|
|
||||||
KeysQueue.Insert(0, BufferId);
|
KeysQueue.Enqueue(BufferId);
|
||||||
|
|
||||||
byte[] AudioOutBuffer = AMemoryHelper.ReadBytes(Context.Memory, Context.Request.SendBuff[0].Position, 0x28);
|
byte[] AudioOutBuffer = AMemoryHelper.ReadBytes(Context.Memory, Context.Request.SendBuff[0].Position, 0x28);
|
||||||
using (MemoryStream MS = new MemoryStream(AudioOutBuffer))
|
using (MemoryStream MS = new MemoryStream(AudioOutBuffer))
|
||||||
|
@ -125,13 +122,9 @@ namespace Ryujinx.OsHle.Objects
|
||||||
{
|
{
|
||||||
long TempKey = 0;
|
long TempKey = 0;
|
||||||
|
|
||||||
if (KeysQueue.Count > 0)
|
if (KeysQueue.Count > 0) TempKey = KeysQueue.Dequeue();
|
||||||
{
|
|
||||||
TempKey = KeysQueue[KeysQueue.Count - 1];
|
|
||||||
KeysQueue.Remove(KeysQueue[KeysQueue.Count - 1]);
|
|
||||||
}
|
|
||||||
|
|
||||||
AMemoryHelper.WriteBytes(Context.Memory, Context.Request.ReceiveBuff[0].Position, System.BitConverter.GetBytes(TempKey));
|
AMemoryHelper.WriteBytes(Context.Memory, Context.Request.ReceiveBuff[0].Position, BitConverter.GetBytes(TempKey));
|
||||||
|
|
||||||
Context.ResponseData.Write((int)TempKey);
|
Context.ResponseData.Write((int)TempKey);
|
||||||
|
|
||||||
|
|
|
@ -563,7 +563,7 @@ namespace Ryujinx.OsHle.Services
|
||||||
NvMap.Kind = Kind;
|
NvMap.Kind = Kind;
|
||||||
}
|
}
|
||||||
|
|
||||||
Console.WriteLine($"NvMapIocAlloc at {NvMap.Address:x16}");
|
Logging.Debug($"NvMapIocAlloc at {NvMap.Address:x16}");
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -69,7 +69,9 @@ namespace Ryujinx.OsHle.Svc
|
||||||
|
|
||||||
if (SvcFuncs.TryGetValue(e.Id, out SvcFunc Func))
|
if (SvcFuncs.TryGetValue(e.Id, out SvcFunc Func))
|
||||||
{
|
{
|
||||||
|
Logging.Trace($"{Func.Method.Name} called.");
|
||||||
Func(Ns, Registers, Memory);
|
Func(Ns, Registers, Memory);
|
||||||
|
Logging.Trace($"{Func.Method.Name} ended.");
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
|
@ -121,7 +121,7 @@ namespace Ryujinx.OsHle.Svc
|
||||||
|
|
||||||
string Str = AMemoryHelper.ReadAsciiString(Memory, Position, (int)Size);
|
string Str = AMemoryHelper.ReadAsciiString(Memory, Position, (int)Size);
|
||||||
|
|
||||||
Console.WriteLine($"SvcOutputDebugString: {Str}");
|
Logging.Info($"SvcOutputDebugString: {Str}");
|
||||||
|
|
||||||
Registers.X0 = (int)SvcResult.Success;
|
Registers.X0 = (int)SvcResult.Success;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue