forked from Mirror/Ryujinx
aloha
This commit is contained in:
commit
b7e1d9930d
230 changed files with 17548 additions and 0 deletions
63
.gitattributes
vendored
Normal file
63
.gitattributes
vendored
Normal file
|
@ -0,0 +1,63 @@
|
|||
###############################################################################
|
||||
# Set default behavior to automatically normalize line endings.
|
||||
###############################################################################
|
||||
* text=auto
|
||||
|
||||
###############################################################################
|
||||
# Set default behavior for command prompt diff.
|
||||
#
|
||||
# This is need for earlier builds of msysgit that does not have it on by
|
||||
# default for csharp files.
|
||||
# Note: This is only used by command line
|
||||
###############################################################################
|
||||
#*.cs diff=csharp
|
||||
|
||||
###############################################################################
|
||||
# Set the merge driver for project and solution files
|
||||
#
|
||||
# Merging from the command prompt will add diff markers to the files if there
|
||||
# are conflicts (Merging from VS is not affected by the settings below, in VS
|
||||
# the diff markers are never inserted). Diff markers may cause the following
|
||||
# file extensions to fail to load in VS. An alternative would be to treat
|
||||
# these files as binary and thus will always conflict and require user
|
||||
# intervention with every merge. To do so, just uncomment the entries below
|
||||
###############################################################################
|
||||
#*.sln merge=binary
|
||||
#*.csproj merge=binary
|
||||
#*.vbproj merge=binary
|
||||
#*.vcxproj merge=binary
|
||||
#*.vcproj merge=binary
|
||||
#*.dbproj merge=binary
|
||||
#*.fsproj merge=binary
|
||||
#*.lsproj merge=binary
|
||||
#*.wixproj merge=binary
|
||||
#*.modelproj merge=binary
|
||||
#*.sqlproj merge=binary
|
||||
#*.wwaproj merge=binary
|
||||
|
||||
###############################################################################
|
||||
# behavior for image files
|
||||
#
|
||||
# image files are treated as binary by default.
|
||||
###############################################################################
|
||||
#*.jpg binary
|
||||
#*.png binary
|
||||
#*.gif binary
|
||||
|
||||
###############################################################################
|
||||
# diff behavior for common document formats
|
||||
#
|
||||
# Convert binary document formats to text before diffing them. This feature
|
||||
# is only available from the command line. Turn it on by uncommenting the
|
||||
# entries below.
|
||||
###############################################################################
|
||||
#*.doc diff=astextplain
|
||||
#*.DOC diff=astextplain
|
||||
#*.docx diff=astextplain
|
||||
#*.DOCX diff=astextplain
|
||||
#*.dot diff=astextplain
|
||||
#*.DOT diff=astextplain
|
||||
#*.pdf diff=astextplain
|
||||
#*.PDF diff=astextplain
|
||||
#*.rtf diff=astextplain
|
||||
#*.RTF diff=astextplain
|
160
.gitignore
vendored
Normal file
160
.gitignore
vendored
Normal file
|
@ -0,0 +1,160 @@
|
|||
## Ignore Visual Studio temporary files, build results, and
|
||||
## files generated by popular Visual Studio add-ons.
|
||||
|
||||
# User-specific files
|
||||
*.suo
|
||||
*.user
|
||||
*.sln.docstates
|
||||
.vs
|
||||
.vscode
|
||||
|
||||
# Build results
|
||||
|
||||
[Dd]ebug/
|
||||
[Rr]elease/
|
||||
x64/
|
||||
build/
|
||||
[Bb]in/
|
||||
[Oo]bj/
|
||||
|
||||
# Enable "build/" folder in the NuGet Packages folder since NuGet packages use it for MSBuild targets
|
||||
!packages/*/build/
|
||||
|
||||
# MSTest test Results
|
||||
[Tt]est[Rr]esult*/
|
||||
[Bb]uild[Ll]og.*
|
||||
|
||||
*_i.c
|
||||
*_p.c
|
||||
*.ilk
|
||||
*.meta
|
||||
*.obj
|
||||
*.pch
|
||||
*.pdb
|
||||
*.pgc
|
||||
*.pgd
|
||||
*.rsp
|
||||
*.sbr
|
||||
*.tlb
|
||||
*.tli
|
||||
*.tlh
|
||||
*.tmp
|
||||
*.tmp_proj
|
||||
*.log
|
||||
*.vspscc
|
||||
*.vssscc
|
||||
.builds
|
||||
*.pidb
|
||||
*.log
|
||||
*.scc
|
||||
|
||||
# Visual C++ cache files
|
||||
ipch/
|
||||
*.aps
|
||||
*.ncb
|
||||
*.opensdf
|
||||
*.sdf
|
||||
*.cachefile
|
||||
|
||||
# Visual Studio profiler
|
||||
*.psess
|
||||
*.vsp
|
||||
*.vspx
|
||||
|
||||
# Guidance Automation Toolkit
|
||||
*.gpState
|
||||
|
||||
# ReSharper is a .NET coding add-in
|
||||
_ReSharper*/
|
||||
*.[Rr]e[Ss]harper
|
||||
|
||||
# TeamCity is a build add-in
|
||||
_TeamCity*
|
||||
|
||||
# DotCover is a Code Coverage Tool
|
||||
*.dotCover
|
||||
|
||||
# NCrunch
|
||||
*.ncrunch*
|
||||
.*crunch*.local.xml
|
||||
|
||||
# Installshield output folder
|
||||
[Ee]xpress/
|
||||
|
||||
# DocProject is a documentation generator add-in
|
||||
DocProject/buildhelp/
|
||||
DocProject/Help/*.HxT
|
||||
DocProject/Help/*.HxC
|
||||
DocProject/Help/*.hhc
|
||||
DocProject/Help/*.hhk
|
||||
DocProject/Help/*.hhp
|
||||
DocProject/Help/Html2
|
||||
DocProject/Help/html
|
||||
|
||||
# Click-Once directory
|
||||
publish/
|
||||
|
||||
# Publish Web Output
|
||||
*.Publish.xml
|
||||
|
||||
# NuGet Packages Directory
|
||||
## TODO: If you have NuGet Package Restore enabled, uncomment the next line
|
||||
#packages/
|
||||
|
||||
# Windows Azure Build Output
|
||||
csx
|
||||
*.build.csdef
|
||||
|
||||
# Windows Store app package directory
|
||||
AppPackages/
|
||||
|
||||
# Others
|
||||
sql/
|
||||
*.Cache
|
||||
ClientBin/
|
||||
[Ss]tyle[Cc]op.*
|
||||
~$*
|
||||
*~
|
||||
*.dbmdl
|
||||
*.[Pp]ublish.xml
|
||||
*.pfx
|
||||
*.publishsettings
|
||||
packages/*
|
||||
*.config
|
||||
|
||||
# RIA/Silverlight projects
|
||||
Generated_Code/
|
||||
|
||||
# Backup & report files from converting an old project file to a newer
|
||||
# Visual Studio version. Backup files are not needed, because we have git ;-)
|
||||
_UpgradeReport_Files/
|
||||
Backup*/
|
||||
UpgradeLog*.XML
|
||||
UpgradeLog*.htm
|
||||
|
||||
# SQL Server files
|
||||
App_Data/*.mdf
|
||||
App_Data/*.ldf
|
||||
|
||||
|
||||
#LightSwitch generated files
|
||||
GeneratedArtifacts/
|
||||
_Pvt_Extensions/
|
||||
ModelManifest.xml
|
||||
|
||||
# =========================
|
||||
# Windows detritus
|
||||
# =========================
|
||||
|
||||
# Windows image file caches
|
||||
Thumbs.db
|
||||
ehthumbs.db
|
||||
|
||||
# Folder config file
|
||||
Desktop.ini
|
||||
|
||||
# Recycle Bin used on file shares
|
||||
$RECYCLE.BIN/
|
||||
|
||||
# Mac desktop service store files
|
||||
.DS_Store
|
366
GLScreen.cs
Normal file
366
GLScreen.cs
Normal file
|
@ -0,0 +1,366 @@
|
|||
// This code was written for the OpenTK library and has been released
|
||||
// to the Public Domain.
|
||||
// It is provided "as is" without express or implied warranty of any kind.
|
||||
|
||||
using Gal;
|
||||
using OpenTK;
|
||||
using OpenTK.Graphics;
|
||||
using OpenTK.Graphics.OpenGL;
|
||||
using System;
|
||||
|
||||
namespace Ryujinx
|
||||
{
|
||||
public class GLScreen : GameWindow
|
||||
{
|
||||
class ScreenTexture : IDisposable
|
||||
{
|
||||
private Switch Ns;
|
||||
private IGalRenderer Renderer;
|
||||
|
||||
private int Width;
|
||||
private int Height;
|
||||
private int TexHandle;
|
||||
|
||||
private int[] Pixels;
|
||||
|
||||
public ScreenTexture(Switch Ns, IGalRenderer Renderer, int Width, int Height)
|
||||
{
|
||||
this.Ns = Ns;
|
||||
this.Renderer = Renderer;
|
||||
this.Width = Width;
|
||||
this.Height = Height;
|
||||
|
||||
Pixels = new int[Width * Height];
|
||||
|
||||
TexHandle = GL.GenTexture();
|
||||
|
||||
GL.BindTexture(TextureTarget.Texture2D, TexHandle);
|
||||
GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMinFilter, (int)TextureMinFilter.Linear);
|
||||
GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMagFilter, (int)TextureMagFilter.Linear);
|
||||
GL.TexImage2D(TextureTarget.Texture2D,
|
||||
0,
|
||||
PixelInternalFormat.Rgba,
|
||||
Width,
|
||||
Height,
|
||||
0,
|
||||
PixelFormat.Rgba,
|
||||
PixelType.UnsignedByte,
|
||||
IntPtr.Zero);
|
||||
}
|
||||
|
||||
public int Texture
|
||||
{
|
||||
get
|
||||
{
|
||||
UploadBitmap();
|
||||
|
||||
return TexHandle;
|
||||
}
|
||||
}
|
||||
|
||||
unsafe void UploadBitmap()
|
||||
{
|
||||
if (Renderer.FrameBufferPtr == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
byte* SrcPtr = (byte*)IntPtr.Add(Ns.Ram, (int)Renderer.FrameBufferPtr);
|
||||
|
||||
for (int Y = 0; Y < Height; Y++)
|
||||
{
|
||||
for (int X = 0; X < Width; X++)
|
||||
{
|
||||
int SrcOffs = GetSwizzleOffset(X, Y, 4);
|
||||
|
||||
Pixels[X + Y * Width] = *((int*)(SrcPtr + SrcOffs));
|
||||
}
|
||||
}
|
||||
|
||||
GL.BindTexture(TextureTarget.Texture2D, TexHandle);
|
||||
GL.TexSubImage2D(TextureTarget.Texture2D,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
Width,
|
||||
Height,
|
||||
PixelFormat.Rgba,
|
||||
PixelType.UnsignedByte,
|
||||
Pixels);
|
||||
}
|
||||
|
||||
private int GetSwizzleOffset(int X, int Y, int Bpp)
|
||||
{
|
||||
int Pos;
|
||||
|
||||
Pos = (Y & 0x7f) >> 4;
|
||||
Pos += (X >> 4) << 3;
|
||||
Pos += (Y >> 7) * ((Width >> 4) << 3);
|
||||
Pos *= 1024;
|
||||
Pos += ((Y & 0xf) >> 3) << 9;
|
||||
Pos += ((X & 0xf) >> 3) << 8;
|
||||
Pos += ((Y & 0x7) >> 1) << 6;
|
||||
Pos += ((X & 0x7) >> 2) << 5;
|
||||
Pos += ((Y & 0x1) >> 0) << 4;
|
||||
Pos += ((X & 0x3) >> 0) << 2;
|
||||
|
||||
return Pos;
|
||||
}
|
||||
|
||||
private bool disposed;
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
Dispose(true);
|
||||
|
||||
GC.SuppressFinalize(this);
|
||||
}
|
||||
|
||||
void Dispose(bool disposing)
|
||||
{
|
||||
if (!disposed)
|
||||
{
|
||||
if (disposing)
|
||||
{
|
||||
GL.DeleteTexture(TexHandle);
|
||||
}
|
||||
|
||||
disposed = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private string VtxShaderSource = @"
|
||||
#version 330 core
|
||||
|
||||
precision highp float;
|
||||
|
||||
layout(location = 0) in vec3 in_position;
|
||||
layout(location = 1) in vec4 in_color;
|
||||
layout(location = 2) in vec2 in_tex_coord;
|
||||
|
||||
out vec4 color;
|
||||
out vec2 tex_coord;
|
||||
|
||||
void main(void) {
|
||||
color = in_color;
|
||||
tex_coord = in_tex_coord;
|
||||
gl_Position = vec4((in_position + vec3(-960, 270, 0)) / vec3(1920, 270, 1), 1);
|
||||
}";
|
||||
|
||||
private string FragShaderSource = @"
|
||||
#version 330 core
|
||||
|
||||
precision highp float;
|
||||
|
||||
uniform sampler2D tex;
|
||||
|
||||
in vec4 color;
|
||||
in vec2 tex_coord;
|
||||
out vec4 out_frag_color;
|
||||
|
||||
void main(void) {
|
||||
out_frag_color = vec4(texture(tex, tex_coord).rgb, color.a);
|
||||
}";
|
||||
|
||||
private int VtxShaderHandle,
|
||||
FragShaderHandle,
|
||||
PrgShaderHandle;
|
||||
|
||||
private int VaoHandle;
|
||||
private int VboHandle;
|
||||
|
||||
private Switch Ns;
|
||||
|
||||
private IGalRenderer Renderer;
|
||||
|
||||
private ScreenTexture ScreenTex;
|
||||
|
||||
public GLScreen(Switch Ns, IGalRenderer Renderer)
|
||||
: base(1280, 720,
|
||||
new GraphicsMode(), "Ryujinx", 0,
|
||||
DisplayDevice.Default, 3, 3,
|
||||
GraphicsContextFlags.ForwardCompatible)
|
||||
{
|
||||
this.Ns = Ns;
|
||||
this.Renderer = Renderer;
|
||||
|
||||
ScreenTex = new ScreenTexture(Ns, Renderer, 1280, 720);
|
||||
}
|
||||
|
||||
protected override void OnLoad (EventArgs e)
|
||||
{
|
||||
VSync = VSyncMode.On;
|
||||
|
||||
CreateShaders();
|
||||
CreateVbo();
|
||||
|
||||
GL.Enable(EnableCap.Blend);
|
||||
GL.BlendFunc(BlendingFactorSrc.SrcAlpha, BlendingFactorDest.OneMinusSrcAlpha);
|
||||
}
|
||||
|
||||
protected override void OnUnload(EventArgs e)
|
||||
{
|
||||
ScreenTex.Dispose();
|
||||
|
||||
GL.DeleteVertexArray(VaoHandle);
|
||||
GL.DeleteBuffer(VboHandle);
|
||||
}
|
||||
|
||||
private void CreateVbo()
|
||||
{
|
||||
VaoHandle = GL.GenVertexArray();
|
||||
VboHandle = GL.GenBuffer();
|
||||
|
||||
uint[] Buffer = new uint[]
|
||||
{
|
||||
0xc4700000, 0x80000000, 0x00000000, 0xffffffff, 0x00000000, 0x00000000, 0x00000000,
|
||||
0x45340000, 0x80000000, 0x00000000, 0xffffffff, 0x00000000, 0x3f800000, 0x00000000,
|
||||
0xc4700000, 0xc4070000, 0x00000000, 0xffffffff, 0x00000000, 0x00000000, 0x3f800000,
|
||||
0x45340000, 0xc4070000, 0x00000000, 0xffffffff, 0x00000000, 0x3f800000, 0x3f800000
|
||||
};
|
||||
|
||||
IntPtr Length = new IntPtr(Buffer.Length * 4);
|
||||
|
||||
GL.BindBuffer(BufferTarget.ArrayBuffer, VboHandle);
|
||||
GL.BufferData(BufferTarget.ArrayBuffer, Length, Buffer, BufferUsageHint.StreamDraw);
|
||||
GL.BindBuffer(BufferTarget.ArrayBuffer, 0);
|
||||
|
||||
GL.BindVertexArray(VaoHandle);
|
||||
|
||||
GL.EnableVertexAttribArray(0);
|
||||
|
||||
GL.BindBuffer(BufferTarget.ArrayBuffer, VboHandle);
|
||||
|
||||
GL.VertexAttribPointer(0, 3, VertexAttribPointerType.Float, false, 28, 0);
|
||||
|
||||
GL.EnableVertexAttribArray(1);
|
||||
|
||||
GL.BindBuffer(BufferTarget.ArrayBuffer, VboHandle);
|
||||
|
||||
GL.VertexAttribPointer(1, 4, VertexAttribPointerType.UnsignedByte, false, 28, 12);
|
||||
|
||||
GL.EnableVertexAttribArray(2);
|
||||
|
||||
GL.BindBuffer(BufferTarget.ArrayBuffer, VboHandle);
|
||||
|
||||
GL.VertexAttribPointer(2, 2, VertexAttribPointerType.Float, false, 28, 20);
|
||||
|
||||
GL.BindVertexArray(0);
|
||||
}
|
||||
|
||||
private void CreateShaders()
|
||||
{
|
||||
VtxShaderHandle = GL.CreateShader(ShaderType.VertexShader);
|
||||
FragShaderHandle = GL.CreateShader(ShaderType.FragmentShader);
|
||||
|
||||
GL.ShaderSource(VtxShaderHandle, VtxShaderSource);
|
||||
GL.ShaderSource(FragShaderHandle, FragShaderSource);
|
||||
GL.CompileShader(VtxShaderHandle);
|
||||
GL.CompileShader(FragShaderHandle);
|
||||
|
||||
PrgShaderHandle = GL.CreateProgram();
|
||||
|
||||
GL.AttachShader(PrgShaderHandle, VtxShaderHandle);
|
||||
GL.AttachShader(PrgShaderHandle, FragShaderHandle);
|
||||
GL.LinkProgram(PrgShaderHandle);
|
||||
GL.UseProgram(PrgShaderHandle);
|
||||
|
||||
int TexLocation = GL.GetUniformLocation(PrgShaderHandle, "tex");
|
||||
|
||||
GL.Uniform1(TexLocation, 0);
|
||||
}
|
||||
|
||||
protected override void OnUpdateFrame(FrameEventArgs e)
|
||||
{
|
||||
unsafe
|
||||
{
|
||||
byte* Ptr = (byte*)IntPtr.Add(Ns.Ram, (int)Ns.Os.HidOffset);
|
||||
|
||||
int State = 0;
|
||||
|
||||
if (Keyboard[OpenTK.Input.Key.Up])
|
||||
{
|
||||
State |= 0x2000;
|
||||
}
|
||||
|
||||
if (Keyboard[OpenTK.Input.Key.Down])
|
||||
{
|
||||
State |= 0x8000;
|
||||
}
|
||||
|
||||
if (Keyboard[OpenTK.Input.Key.Left])
|
||||
{
|
||||
State |= 0x1000;
|
||||
}
|
||||
|
||||
if (Keyboard[OpenTK.Input.Key.Right])
|
||||
{
|
||||
State |= 0x4000;
|
||||
}
|
||||
|
||||
if (Keyboard[OpenTK.Input.Key.A])
|
||||
{
|
||||
State |= 0x1;
|
||||
}
|
||||
|
||||
if (Keyboard[OpenTK.Input.Key.S])
|
||||
{
|
||||
State |= 0x2;
|
||||
}
|
||||
|
||||
if (Keyboard[OpenTK.Input.Key.Z])
|
||||
{
|
||||
State |= 0x4;
|
||||
}
|
||||
|
||||
if (Keyboard[OpenTK.Input.Key.X])
|
||||
{
|
||||
State |= 0x8;
|
||||
}
|
||||
|
||||
if (Keyboard[OpenTK.Input.Key.Enter])
|
||||
{
|
||||
State |= 0x400;
|
||||
}
|
||||
|
||||
if (Keyboard[OpenTK.Input.Key.Tab])
|
||||
{
|
||||
State |= 0x800;
|
||||
}
|
||||
|
||||
*((int*)(Ptr + 0xae38)) = (int)State;
|
||||
}
|
||||
|
||||
if (Keyboard[OpenTK.Input.Key.Escape])
|
||||
{
|
||||
this.Exit();
|
||||
}
|
||||
}
|
||||
|
||||
protected override void OnRenderFrame(FrameEventArgs e)
|
||||
{
|
||||
GL.Viewport(0, 0, 1280, 720);
|
||||
|
||||
GL.Clear(ClearBufferMask.ColorBufferBit | ClearBufferMask.DepthBufferBit);
|
||||
|
||||
RenderFb();
|
||||
|
||||
GL.UseProgram(PrgShaderHandle);
|
||||
|
||||
Renderer.RunActions();
|
||||
Renderer.BindTexture(0);
|
||||
Renderer.Render();
|
||||
|
||||
SwapBuffers();
|
||||
}
|
||||
|
||||
void RenderFb()
|
||||
{
|
||||
GL.ActiveTexture(TextureUnit.Texture0);
|
||||
GL.BindTexture(TextureTarget.Texture2D, ScreenTex.Texture);
|
||||
GL.BindVertexArray(VaoHandle);
|
||||
GL.DrawArrays(PrimitiveType.TriangleStrip, 0, 4);
|
||||
}
|
||||
}
|
||||
}
|
24
LICENSE.txt
Normal file
24
LICENSE.txt
Normal file
|
@ -0,0 +1,24 @@
|
|||
This is free and unencumbered software released into the public domain.
|
||||
|
||||
Anyone is free to copy, modify, publish, use, compile, sell, or
|
||||
distribute this software, either in source code form or as a compiled
|
||||
binary, for any purpose, commercial or non-commercial, and by any
|
||||
means.
|
||||
|
||||
In jurisdictions that recognize copyright laws, the author or authors
|
||||
of this software dedicate any and all copyright interest in the
|
||||
software to the public domain. We make this dedication for the benefit
|
||||
of the public at large and to the detriment of our heirs and
|
||||
successors. We intend this dedication to be an overt act of
|
||||
relinquishment in perpetuity of all present and future rights to this
|
||||
software under copyright law.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
|
||||
OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
||||
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
For more information, please refer to <http://unlicense.org/>
|
57
Program.cs
Normal file
57
Program.cs
Normal file
|
@ -0,0 +1,57 @@
|
|||
using Gal;
|
||||
using Gal.OpenGL;
|
||||
using System;
|
||||
using System.IO;
|
||||
|
||||
namespace Ryujinx
|
||||
{
|
||||
class Program
|
||||
{
|
||||
static void Main(string[] args)
|
||||
{
|
||||
IGalRenderer Renderer = new OpenGLRenderer();
|
||||
|
||||
Switch Ns = new Switch(Renderer);
|
||||
|
||||
if (args.Length == 1)
|
||||
{
|
||||
if (Directory.Exists(args[0]))
|
||||
{
|
||||
string[] RomFsFiles = Directory.GetFiles(args[0], "*.istorage");
|
||||
|
||||
if (RomFsFiles.Length > 0)
|
||||
{
|
||||
Console.WriteLine("Loading as cart with RomFS.");
|
||||
|
||||
Ns.Os.LoadCart(args[0], RomFsFiles[0]);
|
||||
}
|
||||
else
|
||||
{
|
||||
Console.WriteLine("Loading as cart WITHOUT RomFS.");
|
||||
|
||||
Ns.Os.LoadCart(args[0]);
|
||||
}
|
||||
}
|
||||
else if (File.Exists(args[0]))
|
||||
{
|
||||
Console.WriteLine("Loading as homebrew.");
|
||||
|
||||
Ns.Os.LoadProgram(args[0]);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Console.WriteLine("Please specify the folder with the NSOs/IStorage or a NSO/NRO.");
|
||||
}
|
||||
|
||||
using (GLScreen Screen = new GLScreen(Ns, Renderer))
|
||||
{
|
||||
Screen.Run(60.0);
|
||||
}
|
||||
|
||||
Ns.Os.StopAllProcesses();
|
||||
|
||||
Ns.Dispose();
|
||||
}
|
||||
}
|
||||
}
|
12
Ryujinx.csproj
Normal file
12
Ryujinx.csproj
Normal file
|
@ -0,0 +1,12 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFramework>netcoreapp2.0</TargetFramework>
|
||||
<RuntimeIdentifier>win10-x64</RuntimeIdentifier>
|
||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<PackageReference Include="OpenTK.NETCore" Version="1.1.2749.6433" />
|
||||
<PackageReference Include="System.Runtime.CompilerServices.Unsafe" Version="4.4.0" />
|
||||
</ItemGroup>
|
||||
</Project>
|
25
Ryujinx.sln
Normal file
25
Ryujinx.sln
Normal file
|
@ -0,0 +1,25 @@
|
|||
|
||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||
# Visual Studio 15
|
||||
VisualStudioVersion = 15.0.26730.8
|
||||
MinimumVisualStudioVersion = 10.0.40219.1
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ryujinx", "Ryujinx.csproj", "{074045D4-3ED2-4711-9169-E385F2BFB5A0}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Any CPU = Debug|Any CPU
|
||||
Release|Any CPU = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||
{074045D4-3ED2-4711-9169-E385F2BFB5A0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{074045D4-3ED2-4711-9169-E385F2BFB5A0}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{074045D4-3ED2-4711-9169-E385F2BFB5A0}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{074045D4-3ED2-4711-9169-E385F2BFB5A0}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
EndGlobalSection
|
||||
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||
SolutionGuid = {110169B3-3328-4730-8AB0-BA05BEF75C1A}
|
||||
EndGlobalSection
|
||||
EndGlobal
|
57
Ryujinx/Cpu/ABitUtils.cs
Normal file
57
Ryujinx/Cpu/ABitUtils.cs
Normal file
|
@ -0,0 +1,57 @@
|
|||
namespace ChocolArm64
|
||||
{
|
||||
static class ABitUtils
|
||||
{
|
||||
public static int CountBitsSet(long Value)
|
||||
{
|
||||
int Count = 0;
|
||||
|
||||
for (int Bit = 0; Bit < 64; Bit++)
|
||||
{
|
||||
Count += (int)(Value >> Bit) & 1;
|
||||
}
|
||||
|
||||
return Count;
|
||||
}
|
||||
|
||||
public static int HighestBitSet32(int Value)
|
||||
{
|
||||
for (int Bit = 31; Bit >= 0; Bit--)
|
||||
{
|
||||
if (((Value >> Bit) & 1) != 0)
|
||||
{
|
||||
return Bit;
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
public static long Replicate(long Bits, int Size)
|
||||
{
|
||||
long Output = 0;
|
||||
|
||||
for (int Bit = 0; Bit < 64; Bit += Size)
|
||||
{
|
||||
Output |= Bits << Bit;
|
||||
}
|
||||
|
||||
return Output;
|
||||
}
|
||||
|
||||
public static long FillWithOnes(int Bits)
|
||||
{
|
||||
return Bits == 64 ? -1L : (1L << Bits) - 1;
|
||||
}
|
||||
|
||||
public static long RotateRight(long Bits, int Shift, int Size)
|
||||
{
|
||||
return (Bits >> Shift) | (Bits << (Size - Shift));
|
||||
}
|
||||
|
||||
public static bool IsPow2(int Value)
|
||||
{
|
||||
return Value != 0 && (Value & (Value - 1)) == 0;
|
||||
}
|
||||
}
|
||||
}
|
374
Ryujinx/Cpu/AOpCodeTable.cs
Normal file
374
Ryujinx/Cpu/AOpCodeTable.cs
Normal file
|
@ -0,0 +1,374 @@
|
|||
using ChocolArm64.Decoder;
|
||||
using ChocolArm64.Instruction;
|
||||
using System;
|
||||
|
||||
namespace ChocolArm64
|
||||
{
|
||||
static class AOpCodeTable
|
||||
{
|
||||
static AOpCodeTable()
|
||||
{
|
||||
#region "OpCode Table"
|
||||
//Integer
|
||||
Set("x0010001xxxxxxxxxxxxxxxxxxxxxxxx", AInstEmit.Add, typeof(AOpCodeAluImm));
|
||||
Set("x0001011xx0xxxxxxxxxxxxxxxxxxxxx", AInstEmit.Add, typeof(AOpCodeAluRs));
|
||||
Set("x0001011001xxxxxxxxxxxxxxxxxxxxx", AInstEmit.Add, typeof(AOpCodeAluRx));
|
||||
Set("x0110001xxxxxxxxxxxxxxxxxxxxxxxx", AInstEmit.Adds, typeof(AOpCodeAluImm));
|
||||
Set("x0101011xx0xxxxxxxxxxxxxxxxxxxxx", AInstEmit.Adds, typeof(AOpCodeAluRs));
|
||||
Set("x0101011001xxxxxxxxxxxxxxxxxxxxx", AInstEmit.Adds, typeof(AOpCodeAluRx));
|
||||
Set("0xx10000xxxxxxxxxxxxxxxxxxxxxxxx", AInstEmit.Adr, typeof(AOpCodeAdr));
|
||||
Set("1xx10000xxxxxxxxxxxxxxxxxxxxxxxx", AInstEmit.Adrp, typeof(AOpCodeAdr));
|
||||
Set("x00100100xxxxxxxxxxxxxxxxxxxxxxx", AInstEmit.And, typeof(AOpCodeAluImm));
|
||||
Set("x0001010xx0xxxxxxxxxxxxxxxxxxxxx", AInstEmit.And, typeof(AOpCodeAluRs));
|
||||
Set("x11100100xxxxxxxxxxxxxxxxxxxxxxx", AInstEmit.Ands, typeof(AOpCodeAluImm));
|
||||
Set("x1101010xx0xxxxxxxxxxxxxxxxxxxxx", AInstEmit.Ands, typeof(AOpCodeAluRs));
|
||||
Set("x0011010110xxxxx001010xxxxxxxxxx", AInstEmit.Asrv, typeof(AOpCodeAluRs));
|
||||
Set("000101xxxxxxxxxxxxxxxxxxxxxxxxxx", AInstEmit.B, typeof(AOpCodeBImmAl));
|
||||
Set("01010100xxxxxxxxxxxxxxxxxxxxxxxx", AInstEmit.B_Cond, typeof(AOpCodeBImmCond));
|
||||
Set("x01100110xxxxxxxxxxxxxxxxxxxxxxx", AInstEmit.Bfm, typeof(AOpCodeBfm));
|
||||
Set("x0001010xx1xxxxxxxxxxxxxxxxxxxxx", AInstEmit.Bic, typeof(AOpCodeAluRs));
|
||||
Set("x1101010xx1xxxxxxxxxxxxxxxxxxxxx", AInstEmit.Bics, typeof(AOpCodeAluRs));
|
||||
Set("100101xxxxxxxxxxxxxxxxxxxxxxxxxx", AInstEmit.Bl, typeof(AOpCodeBImmAl));
|
||||
Set("11010110001xxxxx000000xxxxxxxxxx", AInstEmit.Blr, typeof(AOpCodeBReg));
|
||||
Set("11010110000xxxxx000000xxxxxxxxxx", AInstEmit.Br, typeof(AOpCodeBReg));
|
||||
Set("x0110101xxxxxxxxxxxxxxxxxxxxxxxx", AInstEmit.Cbnz, typeof(AOpCodeBImmCmp));
|
||||
Set("x0110100xxxxxxxxxxxxxxxxxxxxxxxx", AInstEmit.Cbz, typeof(AOpCodeBImmCmp));
|
||||
Set("x0111010010xxxxxxxxx10xxxxxxxxxx", AInstEmit.Ccmn, typeof(AOpCodeCcmpImm));
|
||||
Set("x0111010010xxxxxxxxx00xxxxxxxxxx", AInstEmit.Ccmn, typeof(AOpCodeCcmpReg));
|
||||
Set("x1111010010xxxxxxxxx10xxxxxxxxxx", AInstEmit.Ccmp, typeof(AOpCodeCcmpImm));
|
||||
Set("x1111010010xxxxxxxxx00xxxxxxxxxx", AInstEmit.Ccmp, typeof(AOpCodeCcmpReg));
|
||||
Set("11010101000000110011xxxx01011111", AInstEmit.Clrex, typeof(AOpCodeSystem));
|
||||
Set("x101101011000000000100xxxxxxxxxx", AInstEmit.Clz, typeof(AOpCodeAlu));
|
||||
Set("x0011010100xxxxxxxxx00xxxxxxxxxx", AInstEmit.Csel, typeof(AOpCodeCsel));
|
||||
Set("x0011010100xxxxxxxxx01xxxxxxxxxx", AInstEmit.Csinc, typeof(AOpCodeCsel));
|
||||
Set("x1011010100xxxxxxxxx00xxxxxxxxxx", AInstEmit.Csinv, typeof(AOpCodeCsel));
|
||||
Set("x1011010100xxxxxxxxx01xxxxxxxxxx", AInstEmit.Csneg, typeof(AOpCodeCsel));
|
||||
Set("11010101000000110011xxxx10111111", AInstEmit.Dmb, typeof(AOpCodeSystem));
|
||||
Set("11010101000000110011xxxx10011111", AInstEmit.Dsb, typeof(AOpCodeSystem));
|
||||
Set("x10100100xxxxxxxxxxxxxxxxxxxxxxx", AInstEmit.Eor, typeof(AOpCodeAluImm));
|
||||
Set("x1001010xx0xxxxxxxxxxxxxxxxxxxxx", AInstEmit.Eor, typeof(AOpCodeAluRs));
|
||||
Set("x00100111x0xxxxxxxxxxxxxxxxxxxxx", AInstEmit.Extr, typeof(AOpCodeAluRs));
|
||||
Set("xx001000110xxxxx1xxxxxxxxxxxxxxx", AInstEmit.Ldar, typeof(AOpCodeMemEx));
|
||||
Set("1x001000011xxxxx1xxxxxxxxxxxxxxx", AInstEmit.Ldaxp, typeof(AOpCodeMemEx));
|
||||
Set("xx001000010xxxxx1xxxxxxxxxxxxxxx", AInstEmit.Ldaxr, typeof(AOpCodeMemEx));
|
||||
Set("<<10100xx1xxxxxxxxxxxxxxxxxxxxxx", AInstEmit.Ldp, typeof(AOpCodeMemPair));
|
||||
Set("xx111000010xxxxxxxxxxxxxxxxxxxxx", AInstEmit.Ldr, typeof(AOpCodeMemImm));
|
||||
Set("xx11100101xxxxxxxxxxxxxxxxxxxxxx", AInstEmit.Ldr, typeof(AOpCodeMemImm));
|
||||
Set("xx111000011xxxxxxxxx10xxxxxxxxxx", AInstEmit.Ldr, typeof(AOpCodeMemReg));
|
||||
Set("xx011000xxxxxxxxxxxxxxxxxxxxxxxx", AInstEmit.LdrLit, typeof(AOpCodeMemLit));
|
||||
Set("0x1110001x0xxxxxxxxxxxxxxxxxxxxx", AInstEmit.Ldrs, typeof(AOpCodeMemImm));
|
||||
Set("0x1110011xxxxxxxxxxxxxxxxxxxxxxx", AInstEmit.Ldrs, typeof(AOpCodeMemImm));
|
||||
Set("10111000100xxxxxxxxxxxxxxxxxxxxx", AInstEmit.Ldrs, typeof(AOpCodeMemImm));
|
||||
Set("1011100110xxxxxxxxxxxxxxxxxxxxxx", AInstEmit.Ldrs, typeof(AOpCodeMemImm));
|
||||
Set("0x1110001x1xxxxxxxxx10xxxxxxxxxx", AInstEmit.Ldrs, typeof(AOpCodeMemReg));
|
||||
Set("10111000101xxxxxxxxx10xxxxxxxxxx", AInstEmit.Ldrs, typeof(AOpCodeMemReg));
|
||||
Set("xx001000010xxxxx0xxxxxxxxxxxxxxx", AInstEmit.Ldxr, typeof(AOpCodeMemEx));
|
||||
Set("1x001000011xxxxx0xxxxxxxxxxxxxxx", AInstEmit.Ldxp, typeof(AOpCodeMemEx));
|
||||
Set("x0011010110xxxxx001000xxxxxxxxxx", AInstEmit.Lslv, typeof(AOpCodeAluRs));
|
||||
Set("x0011010110xxxxx001001xxxxxxxxxx", AInstEmit.Lsrv, typeof(AOpCodeAluRs));
|
||||
Set("x0011011000xxxxx0xxxxxxxxxxxxxxx", AInstEmit.Madd, typeof(AOpCodeMul));
|
||||
Set("x11100101xxxxxxxxxxxxxxxxxxxxxxx", AInstEmit.Movk, typeof(AOpCodeMov));
|
||||
Set("x00100101xxxxxxxxxxxxxxxxxxxxxxx", AInstEmit.Movn, typeof(AOpCodeMov));
|
||||
Set("x10100101xxxxxxxxxxxxxxxxxxxxxxx", AInstEmit.Movz, typeof(AOpCodeMov));
|
||||
Set("110101010011xxxxxxxxxxxxxxxxxxxx", AInstEmit.Mrs, typeof(AOpCodeSystem));
|
||||
Set("110101010001xxxxxxxxxxxxxxxxxxxx", AInstEmit.Msr, typeof(AOpCodeSystem));
|
||||
Set("x0011011000xxxxx1xxxxxxxxxxxxxxx", AInstEmit.Msub, typeof(AOpCodeMul));
|
||||
Set("11010101000000110010000000011111", AInstEmit.Nop, typeof(AOpCodeSystem));
|
||||
Set("x0101010xx1xxxxxxxxxxxxxxxxxxxxx", AInstEmit.Orn, typeof(AOpCodeAluRs));
|
||||
Set("x01100100xxxxxxxxxxxxxxxxxxxxxxx", AInstEmit.Orr, typeof(AOpCodeAluImm));
|
||||
Set("x0101010xx0xxxxxxxxxxxxxxxxxxxxx", AInstEmit.Orr, typeof(AOpCodeAluRs));
|
||||
Set("1111100110xxxxxxxxxxxxxxxxxxxxxx", AInstEmit.Pfrm, typeof(AOpCodeMemImm));
|
||||
Set("11011000xxxxxxxxxxxxxxxxxxxxxxxx", AInstEmit.Pfrm, typeof(AOpCodeMemLit));
|
||||
Set("x101101011000000000000xxxxxxxxxx", AInstEmit.Rbit, typeof(AOpCodeAlu));
|
||||
Set("11010110010xxxxx000000xxxxxxxxxx", AInstEmit.Ret, typeof(AOpCodeBReg));
|
||||
Set("x101101011000000000001xxxxxxxxxx", AInstEmit.Rev16, typeof(AOpCodeAlu));
|
||||
Set("x101101011000000000010xxxxxxxxxx", AInstEmit.Rev32, typeof(AOpCodeAlu));
|
||||
Set("1101101011000000000011xxxxxxxxxx", AInstEmit.Rev64, typeof(AOpCodeAlu));
|
||||
Set("x0011010110xxxxx001011xxxxxxxxxx", AInstEmit.Rorv, typeof(AOpCodeAluRs));
|
||||
Set("x00100110xxxxxxxxxxxxxxxxxxxxxxx", AInstEmit.Sbfm, typeof(AOpCodeBfm));
|
||||
Set("x0011010110xxxxx000011xxxxxxxxxx", AInstEmit.Sdiv, typeof(AOpCodeAluRs));
|
||||
Set("10011011001xxxxx0xxxxxxxxxxxxxxx", AInstEmit.Smaddl, typeof(AOpCodeMul));
|
||||
Set("10011011001xxxxx1xxxxxxxxxxxxxxx", AInstEmit.Smsubl, typeof(AOpCodeMul));
|
||||
Set("10011011010xxxxx0xxxxxxxxxxxxxxx", AInstEmit.Smulh, typeof(AOpCodeMul));
|
||||
Set("xx001000100xxxxx1xxxxxxxxxxxxxxx", AInstEmit.Stlr, typeof(AOpCodeMemEx));
|
||||
Set("1x001000001xxxxx1xxxxxxxxxxxxxxx", AInstEmit.Stlxp, typeof(AOpCodeMemEx));
|
||||
Set("xx001000000xxxxx1xxxxxxxxxxxxxxx", AInstEmit.Stlxr, typeof(AOpCodeMemEx));
|
||||
Set("x010100xx0xxxxxxxxxxxxxxxxxxxxxx", AInstEmit.Stp, typeof(AOpCodeMemPair));
|
||||
Set("xx111000000xxxxxxxxxxxxxxxxxxxxx", AInstEmit.Str, typeof(AOpCodeMemImm));
|
||||
Set("xx11100100xxxxxxxxxxxxxxxxxxxxxx", AInstEmit.Str, typeof(AOpCodeMemImm));
|
||||
Set("xx111000001xxxxxxxxx10xxxxxxxxxx", AInstEmit.Str, typeof(AOpCodeMemReg));
|
||||
Set("1x001000001xxxxx0xxxxxxxxxxxxxxx", AInstEmit.Stxp, typeof(AOpCodeMemEx));
|
||||
Set("xx001000000xxxxx0xxxxxxxxxxxxxxx", AInstEmit.Stxr, typeof(AOpCodeMemEx));
|
||||
Set("x1010001xxxxxxxxxxxxxxxxxxxxxxxx", AInstEmit.Sub, typeof(AOpCodeAluImm));
|
||||
Set("x1001011xx0xxxxxxxxxxxxxxxxxxxxx", AInstEmit.Sub, typeof(AOpCodeAluRs));
|
||||
Set("x1001011001xxxxxxxxxxxxxxxxxxxxx", AInstEmit.Sub, typeof(AOpCodeAluRx));
|
||||
Set("x1110001xxxxxxxxxxxxxxxxxxxxxxxx", AInstEmit.Subs, typeof(AOpCodeAluImm));
|
||||
Set("x1101011xx0xxxxxxxxxxxxxxxxxxxxx", AInstEmit.Subs, typeof(AOpCodeAluRs));
|
||||
Set("x1101011001xxxxxxxxxxxxxxxxxxxxx", AInstEmit.Subs, typeof(AOpCodeAluRx));
|
||||
Set("11010100000xxxxxxxxxxxxxxxx00001", AInstEmit.Svc, typeof(AOpCodeException));
|
||||
Set("1101010100001xxxxxxxxxxxxxxxxxxx", AInstEmit.Sys, typeof(AOpCodeSystem));
|
||||
Set("x0110111xxxxxxxxxxxxxxxxxxxxxxxx", AInstEmit.Tbnz, typeof(AOpCodeBImmTest));
|
||||
Set("x0110110xxxxxxxxxxxxxxxxxxxxxxxx", AInstEmit.Tbz, typeof(AOpCodeBImmTest));
|
||||
Set("x10100110xxxxxxxxxxxxxxxxxxxxxxx", AInstEmit.Ubfm, typeof(AOpCodeBfm));
|
||||
Set("x0011010110xxxxx000010xxxxxxxxxx", AInstEmit.Udiv, typeof(AOpCodeAluRs));
|
||||
Set("10011011101xxxxx0xxxxxxxxxxxxxxx", AInstEmit.Umaddl, typeof(AOpCodeMul));
|
||||
Set("10011011101xxxxx1xxxxxxxxxxxxxxx", AInstEmit.Umsubl, typeof(AOpCodeMul));
|
||||
Set("10011011110xxxxx0xxxxxxxxxxxxxxx", AInstEmit.Umulh, typeof(AOpCodeMul));
|
||||
|
||||
//Vector
|
||||
Set("0x001110xx1xxxxx100001xxxxxxxxxx", AInstEmit.Add_V, typeof(AOpCodeSimdReg));
|
||||
Set("01011110xx110001101110xxxxxxxxxx", AInstEmit.Addp_S, typeof(AOpCodeSimd));
|
||||
Set("0x001110xx1xxxxx101111xxxxxxxxxx", AInstEmit.Addp_V, typeof(AOpCodeSimdReg));
|
||||
Set("0x001110<<110001101110xxxxxxxxxx", AInstEmit.Addv_V, typeof(AOpCodeSimd));
|
||||
Set("0x001110001xxxxx000111xxxxxxxxxx", AInstEmit.And_V, typeof(AOpCodeSimdReg));
|
||||
Set("0x001110011xxxxx000111xxxxxxxxxx", AInstEmit.Bic_V, typeof(AOpCodeSimdReg));
|
||||
Set("0x10111100000xxx<<x101xxxxxxxxxx", AInstEmit.Bic_Vi, typeof(AOpCodeSimdImm));
|
||||
Set("0x101110011xxxxx000111xxxxxxxxxx", AInstEmit.Bsl_V, typeof(AOpCodeSimdReg));
|
||||
Set("0x101110xx1xxxxx100011xxxxxxxxxx", AInstEmit.Cmeq_V, typeof(AOpCodeSimdReg));
|
||||
Set("0x001110xx100000100110xxxxxxxxxx", AInstEmit.Cmeq_V, typeof(AOpCodeSimd));
|
||||
Set("0x001110xx1xxxxx001111xxxxxxxxxx", AInstEmit.Cmge_V, typeof(AOpCodeSimdReg));
|
||||
Set("0x101110xx100000100010xxxxxxxxxx", AInstEmit.Cmge_V, typeof(AOpCodeSimd));
|
||||
Set("0x001110xx1xxxxx001101xxxxxxxxxx", AInstEmit.Cmgt_V, typeof(AOpCodeSimdReg));
|
||||
Set("0x001110xx100000100010xxxxxxxxxx", AInstEmit.Cmgt_V, typeof(AOpCodeSimd));
|
||||
Set("0x101110xx1xxxxx001101xxxxxxxxxx", AInstEmit.Cmhi_V, typeof(AOpCodeSimdReg));
|
||||
Set("0x101110xx1xxxxx001111xxxxxxxxxx", AInstEmit.Cmhs_V, typeof(AOpCodeSimdReg));
|
||||
Set("0x101110xx100000100110xxxxxxxxxx", AInstEmit.Cmle_V, typeof(AOpCodeSimd));
|
||||
Set("0x001110xx100000101010xxxxxxxxxx", AInstEmit.Cmlt_V, typeof(AOpCodeSimd));
|
||||
Set("0x00111000100000010110xxxxxxxxxx", AInstEmit.Cnt_V, typeof(AOpCodeSimd));
|
||||
Set("01011110000xxxxx000001xxxxxxxxxx", AInstEmit.Dup_S, typeof(AOpCodeSimdIns));
|
||||
Set("0x001110000xxxxx000011xxxxxxxxxx", AInstEmit.Dup_Gp, typeof(AOpCodeSimdIns));
|
||||
Set("0x001110000xxxxx000001xxxxxxxxxx", AInstEmit.Dup_V, typeof(AOpCodeSimdIns));
|
||||
Set("0x101110001xxxxx000111xxxxxxxxxx", AInstEmit.Eor_V, typeof(AOpCodeSimdReg));
|
||||
Set("00011110xx100000110000xxxxxxxxxx", AInstEmit.Fabs_S, typeof(AOpCodeSimd));
|
||||
Set("00011110xx1xxxxx001010xxxxxxxxxx", AInstEmit.Fadd_S, typeof(AOpCodeSimdReg));
|
||||
Set("0x0011100x1xxxxx110101xxxxxxxxxx", AInstEmit.Fadd_V, typeof(AOpCodeSimdReg));
|
||||
Set("00011110xx1xxxxxxxxx01xxxxx0xxxx", AInstEmit.Fccmp_S, typeof(AOpCodeSimdFcond));
|
||||
Set("00011110xx1xxxxx001000xxxxx0x000", AInstEmit.Fcmp_S, typeof(AOpCodeSimdReg));
|
||||
Set("00011110xx1xxxxxxxxx11xxxxxxxxxx", AInstEmit.Fcsel_S, typeof(AOpCodeSimdFcond));
|
||||
Set("00011110xx10001xx10000xxxxxxxxxx", AInstEmit.Fcvt_S, typeof(AOpCodeSimd));
|
||||
Set("x0011110xx110000000000xxxxxxxxxx", AInstEmit.Fcvtms_S, typeof(AOpCodeSimdCvt));
|
||||
Set("x0011110xx101000000000xxxxxxxxxx", AInstEmit.Fcvtps_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("x0011110xx011001xxxxxxxxxxxxxxxx", AInstEmit.Fcvtzu_Fix, typeof(AOpCodeSimdCvt));
|
||||
Set("00011110xx1xxxxx000110xxxxxxxxxx", AInstEmit.Fdiv_S, typeof(AOpCodeSimdReg));
|
||||
Set("00011110xx1xxxxx010010xxxxxxxxxx", AInstEmit.Fmax_S, typeof(AOpCodeSimdReg));
|
||||
Set("00011110xx1xxxxx011010xxxxxxxxxx", AInstEmit.Fmaxnm_S, typeof(AOpCodeSimdReg));
|
||||
Set("00011110xx1xxxxx010110xxxxxxxxxx", AInstEmit.Fmin_S, typeof(AOpCodeSimdReg));
|
||||
Set("00011110xx1xxxxx011110xxxxxxxxxx", AInstEmit.Fminnm_S, typeof(AOpCodeSimdReg));
|
||||
Set("0x0011100x1xxxxx110011xxxxxxxxxx", AInstEmit.Fmla_V, typeof(AOpCodeSimdReg));
|
||||
Set("0x0011111<<xxxxx0001x0xxxxxxxxxx", AInstEmit.Fmla_Vs, typeof(AOpCodeSimdRegElem));
|
||||
Set("00011110xx1xxxxxxxx100xxxxxxxxxx", AInstEmit.Fmov_S, typeof(AOpCodeSimdFmov));
|
||||
Set("0xx0111100000xxx111101xxxxxxxxxx", AInstEmit.Fmov_V, typeof(AOpCodeSimdImm));
|
||||
Set("x0011110xx100110000000xxxxxxxxxx", AInstEmit.Fmov_Ftoi, typeof(AOpCodeSimdCvt));
|
||||
Set("x0011110xx100111000000xxxxxxxxxx", AInstEmit.Fmov_Itof, typeof(AOpCodeSimdCvt));
|
||||
Set("x0011110xx101110000000xxxxxxxxxx", AInstEmit.Fmov_Ftoi1, typeof(AOpCodeSimdCvt));
|
||||
Set("x0011110xx101111000000xxxxxxxxxx", AInstEmit.Fmov_Itof1, typeof(AOpCodeSimdCvt));
|
||||
Set("00011110xx1xxxxx000010xxxxxxxxxx", AInstEmit.Fmul_S, typeof(AOpCodeSimdReg));
|
||||
Set("0x1011100x1xxxxx110111xxxxxxxxxx", AInstEmit.Fmul_V, typeof(AOpCodeSimdReg));
|
||||
Set("0x0011111<<xxxxx1001x0xxxxxxxxxx", AInstEmit.Fmul_Vs, typeof(AOpCodeSimdRegElem));
|
||||
Set("00011110xx100001010000xxxxxxxxxx", AInstEmit.Fneg_S, typeof(AOpCodeSimdReg));
|
||||
Set("00011110xx1xxxxx100010xxxxxxxxxx", AInstEmit.Fnmul_S, typeof(AOpCodeSimdReg));
|
||||
Set("00011110xx100110010000xxxxxxxxxx", AInstEmit.Frinta_S, typeof(AOpCodeSimd));
|
||||
Set("00011110xx100101010000xxxxxxxxxx", AInstEmit.Frintm_S, typeof(AOpCodeSimd));
|
||||
Set("00011110xx100001110000xxxxxxxxxx", AInstEmit.Fsqrt_S, typeof(AOpCodeSimd));
|
||||
Set("00011110xx1xxxxx001110xxxxxxxxxx", AInstEmit.Fsub_S, typeof(AOpCodeSimdReg));
|
||||
Set("0x0011101x1xxxxx110101xxxxxxxxxx", AInstEmit.Fsub_V, typeof(AOpCodeSimdReg));
|
||||
Set("01001110000xxxxx000111xxxxxxxxxx", AInstEmit.Ins_Gp, typeof(AOpCodeSimdIns));
|
||||
Set("01101110000xxxxx0xxxx1xxxxxxxxxx", AInstEmit.Ins_V, typeof(AOpCodeSimdIns));
|
||||
Set("0x00110001000000xxxxxxxxxxxxxxxx", AInstEmit.Ld__V, typeof(AOpCodeSimdMemMult));
|
||||
Set("0x001100110xxxxxxxxxxxxxxxxxxxxx", AInstEmit.Ld__V, typeof(AOpCodeSimdMemMult));
|
||||
Set("xx10110xx1xxxxxxxxxxxxxxxxxxxxxx", AInstEmit.Ldp, typeof(AOpCodeSimdMemPair));
|
||||
Set("xx111100x10xxxxxxxxx00xxxxxxxxxx", AInstEmit.Ldr, typeof(AOpCodeSimdMemImm));
|
||||
Set("xx111100x10xxxxxxxxx01xxxxxxxxxx", AInstEmit.Ldr, typeof(AOpCodeSimdMemImm));
|
||||
Set("xx111100x10xxxxxxxxx11xxxxxxxxxx", AInstEmit.Ldr, typeof(AOpCodeSimdMemImm));
|
||||
Set("xx111101x1xxxxxxxxxxxxxxxxxxxxxx", AInstEmit.Ldr, typeof(AOpCodeSimdMemImm));
|
||||
Set("xx111100x11xxxxxxxxx10xxxxxxxxxx", AInstEmit.Ldr, typeof(AOpCodeSimdMemReg));
|
||||
Set("xx011100xxxxxxxxxxxxxxxxxxxxxxxx", AInstEmit.LdrLit, typeof(AOpCodeSimdMemLit));
|
||||
Set("0x001110xx1xxxxx100101xxxxxxxxxx", AInstEmit.Mla_V, typeof(AOpCodeSimdReg));
|
||||
Set("0x00111100000xxx0xx001xxxxxxxxxx", AInstEmit.Movi_V, typeof(AOpCodeSimdImm));
|
||||
Set("0x00111100000xxx10x001xxxxxxxxxx", AInstEmit.Movi_V, typeof(AOpCodeSimdImm));
|
||||
Set("0x00111100000xxx110x01xxxxxxxxxx", AInstEmit.Movi_V, typeof(AOpCodeSimdImm));
|
||||
Set("0xx0111100000xxx111001xxxxxxxxxx", AInstEmit.Movi_V, typeof(AOpCodeSimdImm));
|
||||
Set("0x001110xx1xxxxx100111xxxxxxxxxx", AInstEmit.Mul_V, typeof(AOpCodeSimdReg));
|
||||
Set("0x10111100000xxx0xx001xxxxxxxxxx", AInstEmit.Mvni_V, typeof(AOpCodeSimdImm));
|
||||
Set("0x10111100000xxx10x001xxxxxxxxxx", AInstEmit.Mvni_V, typeof(AOpCodeSimdImm));
|
||||
Set("0x10111100000xxx110x01xxxxxxxxxx", AInstEmit.Mvni_V, typeof(AOpCodeSimdImm));
|
||||
Set("0x101110xx100000101110xxxxxxxxxx", AInstEmit.Neg_V, typeof(AOpCodeSimdReg));
|
||||
Set("0x10111000100000010110xxxxxxxxxx", AInstEmit.Not_V, typeof(AOpCodeSimd));
|
||||
Set("0x001110101xxxxx000111xxxxxxxxxx", AInstEmit.Orr_V, typeof(AOpCodeSimdReg));
|
||||
Set("0x00111100000xxx<<x101xxxxxxxxxx", AInstEmit.Orr_Vi, typeof(AOpCodeSimdImm));
|
||||
Set("0x001110<<1xxxxx000100xxxxxxxxxx", AInstEmit.Saddw_V, typeof(AOpCodeSimdReg));
|
||||
Set("0x0011100x100001110110xxxxxxxxxx", AInstEmit.Scvtf_V, typeof(AOpCodeSimd));
|
||||
Set("010111110>>>>xxx010101xxxxxxxxxx", AInstEmit.Shl_S, typeof(AOpCodeSimdShImm));
|
||||
Set("0x0011110>>>>xxx010101xxxxxxxxxx", AInstEmit.Shl_V, typeof(AOpCodeSimdShImm));
|
||||
Set("0x001110<<1xxxxx011001xxxxxxxxxx", AInstEmit.Smax_V, typeof(AOpCodeSimdReg));
|
||||
Set("0x001110<<1xxxxx011011xxxxxxxxxx", AInstEmit.Smin_V, typeof(AOpCodeSimdReg));
|
||||
Set("0x00111100>>>xxx101001xxxxxxxxxx", AInstEmit.Sshll_V, typeof(AOpCodeSimdShImm));
|
||||
Set("010111110>>>>xxx000001xxxxxxxxxx", AInstEmit.Sshr_S, typeof(AOpCodeSimdShImm));
|
||||
Set("0x0011110>>>>xxx000001xxxxxxxxxx", AInstEmit.Sshr_V, typeof(AOpCodeSimdShImm));
|
||||
Set("0x00110000000000xxxxxxxxxxxxxxxx", AInstEmit.St__V, typeof(AOpCodeSimdMemMult));
|
||||
Set("0x001100100xxxxxxxxxxxxxxxxxxxxx", AInstEmit.St__V, typeof(AOpCodeSimdMemMult));
|
||||
Set("xx10110xx0xxxxxxxxxxxxxxxxxxxxxx", AInstEmit.Stp, typeof(AOpCodeSimdMemPair));
|
||||
Set("xx111100x00xxxxxxxxx00xxxxxxxxxx", AInstEmit.Str, typeof(AOpCodeSimdMemImm));
|
||||
Set("xx111100x00xxxxxxxxx01xxxxxxxxxx", AInstEmit.Str, typeof(AOpCodeSimdMemImm));
|
||||
Set("xx111100x00xxxxxxxxx11xxxxxxxxxx", AInstEmit.Str, typeof(AOpCodeSimdMemImm));
|
||||
Set("xx111101x0xxxxxxxxxxxxxxxxxxxxxx", AInstEmit.Str, typeof(AOpCodeSimdMemImm));
|
||||
Set("xx111100x01xxxxxxxxx10xxxxxxxxxx", AInstEmit.Str, typeof(AOpCodeSimdMemReg));
|
||||
Set("01111110xx1xxxxx100001xxxxxxxxxx", AInstEmit.Sub_S, typeof(AOpCodeSimdReg));
|
||||
Set("0x101110xx1xxxxx100001xxxxxxxxxx", AInstEmit.Sub_V, typeof(AOpCodeSimdReg));
|
||||
Set("x0011110xx100010000000xxxxxxxxxx", AInstEmit.Scvtf_Gp, typeof(AOpCodeSimdCvt));
|
||||
Set("010111100x100001110110xxxxxxxxxx", AInstEmit.Scvtf_S, typeof(AOpCodeSimd));
|
||||
Set("0x001110000xxxxx0xx000xxxxxxxxxx", AInstEmit.Tbl_V, typeof(AOpCodeSimdTbl));
|
||||
Set("001011100x110000001110xxxxxxxxxx", AInstEmit.Uaddlv_V, typeof(AOpCodeSimd));
|
||||
Set("01101110<<110000001110xxxxxxxxxx", AInstEmit.Uaddlv_V, typeof(AOpCodeSimd));
|
||||
Set("0x101110<<1xxxxx000100xxxxxxxxxx", AInstEmit.Uaddw_V, typeof(AOpCodeSimdReg));
|
||||
Set("x0011110xx100011000000xxxxxxxxxx", AInstEmit.Ucvtf_Gp, typeof(AOpCodeSimdCvt));
|
||||
Set("011111100x100001110110xxxxxxxxxx", AInstEmit.Ucvtf_V, typeof(AOpCodeSimdReg));
|
||||
Set("0x001110000xxxxx001111xxxxxxxxxx", AInstEmit.Umov_S, typeof(AOpCodeSimdIns));
|
||||
Set("0x101110xx1xxxxx010001xxxxxxxxxx", AInstEmit.Ushl_V, typeof(AOpCodeSimdReg));
|
||||
Set("0x10111100>>>xxx101001xxxxxxxxxx", AInstEmit.Ushll_V, typeof(AOpCodeSimdShImm));
|
||||
Set("0x1011110>>>>xxx000001xxxxxxxxxx", AInstEmit.Ushr_V, typeof(AOpCodeSimdShImm));
|
||||
Set("0x1011110>>>>xxx000101xxxxxxxxxx", AInstEmit.Usra_V, typeof(AOpCodeSimdShImm));
|
||||
Set("0x001110xx0xxxxx000110xxxxxxxxxx", AInstEmit.Uzp1_V, typeof(AOpCodeSimdReg));
|
||||
Set("0x001110<<100001001010xxxxxxxxxx", AInstEmit.Xtn_V, typeof(AOpCodeSimd));
|
||||
#endregion
|
||||
}
|
||||
|
||||
private class TreeNode
|
||||
{
|
||||
public int Mask;
|
||||
public int Value;
|
||||
|
||||
public TreeNode Next;
|
||||
public TreeNode Child;
|
||||
|
||||
public AInst Inst;
|
||||
|
||||
public TreeNode(int Mask, int Value, AInst Inst)
|
||||
{
|
||||
this.Mask = Mask;
|
||||
this.Value = Value;
|
||||
this.Inst = Inst;
|
||||
}
|
||||
}
|
||||
|
||||
private static TreeNode Root;
|
||||
|
||||
private static void Set(string Encoding, AInstEmitter Emitter, Type Type)
|
||||
{
|
||||
Set(Encoding, new AInst(Emitter, Type));
|
||||
}
|
||||
|
||||
private static void Set(string Encoding, AInst Inst)
|
||||
{
|
||||
int Bit = Encoding.Length - 1;
|
||||
int Value = 0;
|
||||
int XMask = 0;
|
||||
int ZCount = 0;
|
||||
int OCount = 0;
|
||||
|
||||
int[] ZPos = new int[Encoding.Length];
|
||||
int[] OPos = new int[Encoding.Length];
|
||||
|
||||
for (int Index = 0; Index < Encoding.Length; Index++, Bit--)
|
||||
{
|
||||
//Note: < and > are used on special encodings.
|
||||
//The < means that we should never have ALL bits with the '<' set.
|
||||
//So, when the encoding has <<, it means that 00, 01, and 10 are valid,
|
||||
//but not 11. <<< is 000, 001, ..., 110 but NOT 111, and so on...
|
||||
//For >, the invalid value is zero. So, for << 01, 10 and 11 are valid,
|
||||
//but 00 isn't.
|
||||
switch (Encoding[Index])
|
||||
{
|
||||
case '0': /* Do nothing. */ break;
|
||||
case '1': Value |= 1 << Bit; break;
|
||||
case 'x': XMask |= 1 << Bit; break;
|
||||
|
||||
case '<': OPos[OCount++] = Bit; break;
|
||||
case '>': ZPos[ZCount++] = Bit; break;
|
||||
|
||||
default: throw new ArgumentException(nameof(Encoding));
|
||||
}
|
||||
}
|
||||
|
||||
if (ZCount + OCount == 0)
|
||||
{
|
||||
InsertTop(XMask, Value, Inst);
|
||||
}
|
||||
else if ((ZCount & OCount) != 0)
|
||||
{
|
||||
for (int OCtr = 0; (uint)OCtr < (1 << OCount) - 1; OCtr++)
|
||||
{
|
||||
int OVal = Value;
|
||||
|
||||
for (int O = 0; O < OCount; O++)
|
||||
{
|
||||
OVal |= ((OCtr >> O) & 1) << OPos[O];
|
||||
}
|
||||
|
||||
InsertWithCtr(1, 1 << ZCount, ZCount, ZPos, XMask, OVal, Inst);
|
||||
}
|
||||
}
|
||||
else if (ZCount != 0)
|
||||
{
|
||||
InsertWithCtr(1, 1 << ZCount, ZCount, ZPos, XMask, Value, Inst);
|
||||
}
|
||||
else if (OCount != 0)
|
||||
{
|
||||
InsertWithCtr(0, (1 << OCount) - 1, OCount, OPos, XMask, Value, Inst);
|
||||
}
|
||||
}
|
||||
|
||||
private static void InsertWithCtr(
|
||||
int Start,
|
||||
int End,
|
||||
int Cnt,
|
||||
int[] Pos,
|
||||
int XMask,
|
||||
int Value,
|
||||
AInst Inst)
|
||||
{
|
||||
for (int Ctr = Start; (uint)Ctr < End; Ctr++)
|
||||
{
|
||||
int Val = Value;
|
||||
|
||||
for (int Index = 0; Index < Cnt; Index++)
|
||||
{
|
||||
Val |= ((Ctr >> Index) & 1) << Pos[Index];
|
||||
}
|
||||
|
||||
InsertTop(XMask, Val, Inst);
|
||||
}
|
||||
}
|
||||
|
||||
private static void InsertTop(int XMask, int Value, AInst Inst)
|
||||
{
|
||||
TreeNode Next = Root;
|
||||
|
||||
Root = new TreeNode(~XMask, Value, Inst);
|
||||
|
||||
Root.Next = Next;
|
||||
}
|
||||
|
||||
public static AInst GetInst(int OpCode)
|
||||
{
|
||||
TreeNode Node = Root;
|
||||
|
||||
do
|
||||
{
|
||||
if ((OpCode & Node.Mask) == Node.Value)
|
||||
{
|
||||
return Node.Inst;
|
||||
}
|
||||
}
|
||||
while ((Node = Node.Next) != null);
|
||||
|
||||
return AInst.Undefined;
|
||||
}
|
||||
}
|
||||
}
|
74
Ryujinx/Cpu/AThread.cs
Normal file
74
Ryujinx/Cpu/AThread.cs
Normal file
|
@ -0,0 +1,74 @@
|
|||
using ChocolArm64.Memory;
|
||||
using ChocolArm64.State;
|
||||
using System;
|
||||
using System.Threading;
|
||||
|
||||
namespace ChocolArm64
|
||||
{
|
||||
class AThread
|
||||
{
|
||||
public ARegisters Registers { get; private set; }
|
||||
public AMemory Memory { get; private set; }
|
||||
|
||||
private ATranslator Translator;
|
||||
private Thread Work;
|
||||
|
||||
public event EventHandler WorkFinished;
|
||||
|
||||
public int ThreadId => Registers.ThreadId;
|
||||
|
||||
public bool IsAlive => Work.IsAlive;
|
||||
|
||||
public long EntryPoint { get; private set; }
|
||||
public int Priority { get; private set; }
|
||||
|
||||
public AThread(AMemory Memory, long EntryPoint = 0, int Priority = 0)
|
||||
{
|
||||
this.Memory = Memory;
|
||||
this.EntryPoint = EntryPoint;
|
||||
this.Priority = Priority;
|
||||
|
||||
Registers = new ARegisters();
|
||||
Translator = new ATranslator(this);
|
||||
}
|
||||
|
||||
public void StopExecution() => Translator.StopExecution();
|
||||
|
||||
public void Execute() => Execute(EntryPoint);
|
||||
|
||||
public void Execute(long EntryPoint)
|
||||
{
|
||||
Work = new Thread(delegate()
|
||||
{
|
||||
Translator.ExecuteSubroutine(EntryPoint);
|
||||
|
||||
Memory.RemoveMonitor(ThreadId);
|
||||
|
||||
WorkFinished?.Invoke(this, EventArgs.Empty);
|
||||
});
|
||||
|
||||
if (Priority < 12)
|
||||
{
|
||||
Work.Priority = ThreadPriority.Highest;
|
||||
}
|
||||
else if (Priority < 24)
|
||||
{
|
||||
Work.Priority = ThreadPriority.AboveNormal;
|
||||
}
|
||||
else if (Priority < 36)
|
||||
{
|
||||
Work.Priority = ThreadPriority.Normal;
|
||||
}
|
||||
else if (Priority < 48)
|
||||
{
|
||||
Work.Priority = ThreadPriority.BelowNormal;
|
||||
}
|
||||
else
|
||||
{
|
||||
Work.Priority = ThreadPriority.Lowest;
|
||||
}
|
||||
|
||||
Work.Start();
|
||||
}
|
||||
}
|
||||
}
|
104
Ryujinx/Cpu/ATranslatedSub.cs
Normal file
104
Ryujinx/Cpu/ATranslatedSub.cs
Normal file
|
@ -0,0 +1,104 @@
|
|||
using ChocolArm64.Memory;
|
||||
using ChocolArm64.State;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Reflection;
|
||||
using System.Reflection.Emit;
|
||||
|
||||
namespace ChocolArm64
|
||||
{
|
||||
class ATranslatedSub
|
||||
{
|
||||
private delegate long AA64Subroutine(ARegisters Register, AMemory Memory);
|
||||
|
||||
private AA64Subroutine ExecDelegate;
|
||||
|
||||
private bool HasDelegate;
|
||||
|
||||
public static Type[] FixedArgTypes { get; private set; }
|
||||
|
||||
public static int RegistersArgIdx { get; private set; }
|
||||
public static int MemoryArgIdx { get; private set; }
|
||||
|
||||
public DynamicMethod Method { get; private set; }
|
||||
|
||||
public HashSet<long> SubCalls { get; private set; }
|
||||
|
||||
public List<ARegister> Params { get; private set; }
|
||||
|
||||
public bool NeedsReJit { get; private set; }
|
||||
|
||||
public ATranslatedSub()
|
||||
{
|
||||
SubCalls = new HashSet<long>();
|
||||
}
|
||||
|
||||
public ATranslatedSub(DynamicMethod Method, List<ARegister> Params) : this()
|
||||
{
|
||||
if (Params == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(Params));
|
||||
}
|
||||
|
||||
this.Method = Method;
|
||||
this.Params = Params;
|
||||
}
|
||||
|
||||
static ATranslatedSub()
|
||||
{
|
||||
MethodInfo MthdInfo = typeof(AA64Subroutine).GetMethod("Invoke");
|
||||
|
||||
ParameterInfo[] Params = MthdInfo.GetParameters();
|
||||
|
||||
FixedArgTypes = new Type[Params.Length];
|
||||
|
||||
for (int Index = 0; Index < Params.Length; Index++)
|
||||
{
|
||||
Type ParamType = Params[Index].ParameterType;
|
||||
|
||||
FixedArgTypes[Index] = ParamType;
|
||||
|
||||
if (ParamType == typeof(ARegisters))
|
||||
{
|
||||
RegistersArgIdx = Index;
|
||||
}
|
||||
else if (ParamType == typeof(AMemory))
|
||||
{
|
||||
MemoryArgIdx = Index;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public long Execute(ARegisters Registers, AMemory Memory)
|
||||
{
|
||||
if (!HasDelegate)
|
||||
{
|
||||
string Name = $"{Method.Name}_Dispatch";
|
||||
|
||||
DynamicMethod Mthd = new DynamicMethod(Name, typeof(long), FixedArgTypes);
|
||||
|
||||
ILGenerator Generator = Mthd.GetILGenerator();
|
||||
|
||||
Generator.EmitLdargSeq(FixedArgTypes.Length);
|
||||
|
||||
foreach (ARegister Reg in Params)
|
||||
{
|
||||
Generator.EmitLdarg(RegistersArgIdx);
|
||||
|
||||
Generator.Emit(OpCodes.Ldfld, Reg.GetField());
|
||||
}
|
||||
|
||||
Generator.Emit(OpCodes.Call, Method);
|
||||
Generator.Emit(OpCodes.Ret);
|
||||
|
||||
ExecDelegate = (AA64Subroutine)Mthd.CreateDelegate(typeof(AA64Subroutine));
|
||||
|
||||
HasDelegate = true;
|
||||
}
|
||||
|
||||
return ExecDelegate(Registers, Memory);
|
||||
}
|
||||
|
||||
public void MarkForReJit() => NeedsReJit = true;
|
||||
}
|
||||
}
|
106
Ryujinx/Cpu/ATranslator.cs
Normal file
106
Ryujinx/Cpu/ATranslator.cs
Normal file
|
@ -0,0 +1,106 @@
|
|||
using ChocolArm64.Decoder;
|
||||
using ChocolArm64.Instruction;
|
||||
using ChocolArm64.Translation;
|
||||
using System.Collections.Generic;
|
||||
using System.Reflection.Emit;
|
||||
|
||||
namespace ChocolArm64
|
||||
{
|
||||
class ATranslator
|
||||
{
|
||||
private Dictionary<long, ATranslatedSub> CachedSubs;
|
||||
|
||||
public AThread Thread { get; private set; }
|
||||
|
||||
private bool KeepRunning;
|
||||
|
||||
public ATranslator(AThread Parent)
|
||||
{
|
||||
this.Thread = Parent;
|
||||
|
||||
CachedSubs = new Dictionary<long, ATranslatedSub>();
|
||||
|
||||
KeepRunning = true;
|
||||
}
|
||||
|
||||
public void StopExecution() => KeepRunning = false;
|
||||
|
||||
public void ExecuteSubroutine(long Position)
|
||||
{
|
||||
do
|
||||
{
|
||||
if (CachedSubs.TryGetValue(Position, out ATranslatedSub Sub) && !Sub.NeedsReJit)
|
||||
{
|
||||
Position = Sub.Execute(Thread.Registers, Thread.Memory);
|
||||
}
|
||||
else
|
||||
{
|
||||
Position = TranslateSubroutine(Position).Execute(Thread.Registers, Thread.Memory);
|
||||
}
|
||||
}
|
||||
while (Position != 0 && KeepRunning);
|
||||
}
|
||||
|
||||
public bool TryGetCachedSub(AOpCode OpCode, out ATranslatedSub Sub)
|
||||
{
|
||||
if (OpCode.Emitter != AInstEmit.Bl)
|
||||
{
|
||||
Sub = null;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
return TryGetCachedSub(((AOpCodeBImmAl)OpCode).Imm, out Sub);
|
||||
}
|
||||
|
||||
public bool TryGetCachedSub(long Position, out ATranslatedSub Sub)
|
||||
{
|
||||
return CachedSubs.TryGetValue(Position, out Sub);
|
||||
}
|
||||
|
||||
public bool HasCachedSub(long Position)
|
||||
{
|
||||
return CachedSubs.ContainsKey(Position);
|
||||
}
|
||||
|
||||
private ATranslatedSub TranslateSubroutine(long Position)
|
||||
{
|
||||
(ABlock[] Graph, ABlock Root) Cfg = ADecoder.DecodeSubroutine(this, Position);
|
||||
|
||||
AILEmitterCtx Context = new AILEmitterCtx(
|
||||
this,
|
||||
Cfg.Graph,
|
||||
Cfg.Root);
|
||||
|
||||
if (Context.CurrBlock.Position != Position)
|
||||
{
|
||||
Context.Emit(OpCodes.Br, Context.GetLabel(Position));
|
||||
}
|
||||
|
||||
do
|
||||
{
|
||||
Context.EmitOpCode();
|
||||
}
|
||||
while (Context.AdvanceOpCode());
|
||||
|
||||
//Mark all methods that calls this method for ReJiting,
|
||||
//since we can now call it directly which is faster.
|
||||
foreach (ATranslatedSub TS in CachedSubs.Values)
|
||||
{
|
||||
if (TS.SubCalls.Contains(Position))
|
||||
{
|
||||
TS.MarkForReJit();
|
||||
}
|
||||
}
|
||||
|
||||
ATranslatedSub Subroutine = Context.GetSubroutine();
|
||||
|
||||
if (!CachedSubs.TryAdd(Position, Subroutine))
|
||||
{
|
||||
CachedSubs[Position] = Subroutine;
|
||||
}
|
||||
|
||||
return Subroutine;
|
||||
}
|
||||
}
|
||||
}
|
35
Ryujinx/Cpu/Decoder/ABlock.cs
Normal file
35
Ryujinx/Cpu/Decoder/ABlock.cs
Normal file
|
@ -0,0 +1,35 @@
|
|||
using System.Collections.Generic;
|
||||
|
||||
namespace ChocolArm64.Decoder
|
||||
{
|
||||
class ABlock
|
||||
{
|
||||
public long Position { get; set; }
|
||||
public long EndPosition { get; set; }
|
||||
|
||||
public ABlock Next { get; set; }
|
||||
public ABlock Branch { get; set; }
|
||||
|
||||
public List<AOpCode> OpCodes { get; private set; }
|
||||
|
||||
public ABlock()
|
||||
{
|
||||
OpCodes = new List<AOpCode>();
|
||||
}
|
||||
|
||||
public ABlock(long Position) : this()
|
||||
{
|
||||
this.Position = Position;
|
||||
}
|
||||