aloha
This commit is contained in:
commit
b7e1d9930d
230 changed files with 17548 additions and 0 deletions
8
Ryujinx/Cpu/State/ACoreType.cs
Normal file
8
Ryujinx/Cpu/State/ACoreType.cs
Normal file
|
@ -0,0 +1,8 @@
|
|||
namespace ChocolArm64.State
|
||||
{
|
||||
public enum ACoreType
|
||||
{
|
||||
CortexA53,
|
||||
CortexA57
|
||||
}
|
||||
}
|
23
Ryujinx/Cpu/State/APState.cs
Normal file
23
Ryujinx/Cpu/State/APState.cs
Normal file
|
@ -0,0 +1,23 @@
|
|||
using System;
|
||||
|
||||
namespace ChocolArm64.State
|
||||
{
|
||||
[Flags]
|
||||
public enum APState
|
||||
{
|
||||
VBit = 28,
|
||||
CBit = 29,
|
||||
ZBit = 30,
|
||||
NBit = 31,
|
||||
|
||||
V = 1 << VBit,
|
||||
C = 1 << CBit,
|
||||
Z = 1 << ZBit,
|
||||
N = 1 << NBit,
|
||||
|
||||
NZ = N | Z,
|
||||
CV = C | V,
|
||||
|
||||
NZCV = NZ | CV
|
||||
}
|
||||
}
|
142
Ryujinx/Cpu/State/ARegister.cs
Normal file
142
Ryujinx/Cpu/State/ARegister.cs
Normal file
|
@ -0,0 +1,142 @@
|
|||
using System;
|
||||
using System.Reflection;
|
||||
|
||||
namespace ChocolArm64.State
|
||||
{
|
||||
struct ARegister
|
||||
{
|
||||
public int Index;
|
||||
|
||||
public ARegisterType Type;
|
||||
|
||||
public ARegister(int Index, ARegisterType Type)
|
||||
{
|
||||
this.Index = Index;
|
||||
this.Type = Type;
|
||||
}
|
||||
|
||||
public override int GetHashCode()
|
||||
{
|
||||
return (ushort)Index | ((ushort)Type << 16);
|
||||
}
|
||||
|
||||
public override bool Equals(object Obj)
|
||||
{
|
||||
return Obj is ARegister Reg &&
|
||||
Reg.Index == Index &&
|
||||
Reg.Type == Type;
|
||||
}
|
||||
|
||||
public FieldInfo GetField()
|
||||
{
|
||||
switch (Type)
|
||||
{
|
||||
case ARegisterType.Flag: return GetFieldFlag();
|
||||
case ARegisterType.Int: return GetFieldInt();
|
||||
case ARegisterType.Vector: return GetFieldVector();
|
||||
}
|
||||
|
||||
throw new InvalidOperationException();
|
||||
}
|
||||
|
||||
private FieldInfo GetFieldFlag()
|
||||
{
|
||||
switch ((APState)Index)
|
||||
{
|
||||
case APState.VBit: return GetField(nameof(ARegisters.Overflow));
|
||||
case APState.CBit: return GetField(nameof(ARegisters.Carry));
|
||||
case APState.ZBit: return GetField(nameof(ARegisters.Zero));
|
||||
case APState.NBit: return GetField(nameof(ARegisters.Negative));
|
||||
}
|
||||
|
||||
throw new InvalidOperationException();
|
||||
}
|
||||
|
||||
private FieldInfo GetFieldInt()
|
||||
{
|
||||
switch (Index)
|
||||
{
|
||||
case 0: return GetField(nameof(ARegisters.X0));
|
||||
case 1: return GetField(nameof(ARegisters.X1));
|
||||
case 2: return GetField(nameof(ARegisters.X2));
|
||||
case 3: return GetField(nameof(ARegisters.X3));
|
||||
case 4: return GetField(nameof(ARegisters.X4));
|
||||
case 5: return GetField(nameof(ARegisters.X5));
|
||||
case 6: return GetField(nameof(ARegisters.X6));
|
||||
case 7: return GetField(nameof(ARegisters.X7));
|
||||
case 8: return GetField(nameof(ARegisters.X8));
|
||||
case 9: return GetField(nameof(ARegisters.X9));
|
||||
case 10: return GetField(nameof(ARegisters.X10));
|
||||
case 11: return GetField(nameof(ARegisters.X11));
|
||||
case 12: return GetField(nameof(ARegisters.X12));
|
||||
case 13: return GetField(nameof(ARegisters.X13));
|
||||
case 14: return GetField(nameof(ARegisters.X14));
|
||||
case 15: return GetField(nameof(ARegisters.X15));
|
||||
case 16: return GetField(nameof(ARegisters.X16));
|
||||
case 17: return GetField(nameof(ARegisters.X17));
|
||||
case 18: return GetField(nameof(ARegisters.X18));
|
||||
case 19: return GetField(nameof(ARegisters.X19));
|
||||
case 20: return GetField(nameof(ARegisters.X20));
|
||||
case 21: return GetField(nameof(ARegisters.X21));
|
||||
case 22: return GetField(nameof(ARegisters.X22));
|
||||
case 23: return GetField(nameof(ARegisters.X23));
|
||||
case 24: return GetField(nameof(ARegisters.X24));
|
||||
case 25: return GetField(nameof(ARegisters.X25));
|
||||
case 26: return GetField(nameof(ARegisters.X26));
|
||||
case 27: return GetField(nameof(ARegisters.X27));
|
||||
case 28: return GetField(nameof(ARegisters.X28));
|
||||
case 29: return GetField(nameof(ARegisters.X29));
|
||||
case 30: return GetField(nameof(ARegisters.X30));
|
||||
case 31: return GetField(nameof(ARegisters.X31));
|
||||
}
|
||||
|
||||
throw new InvalidOperationException();
|
||||
}
|
||||
|
||||
private FieldInfo GetFieldVector()
|
||||
{
|
||||
switch (Index)
|
||||
{
|
||||
case 0: return GetField(nameof(ARegisters.V0));
|
||||
case 1: return GetField(nameof(ARegisters.V1));
|
||||
case 2: return GetField(nameof(ARegisters.V2));
|
||||
case 3: return GetField(nameof(ARegisters.V3));
|
||||
case 4: return GetField(nameof(ARegisters.V4));
|
||||
case 5: return GetField(nameof(ARegisters.V5));
|
||||
case 6: return GetField(nameof(ARegisters.V6));
|
||||
case 7: return GetField(nameof(ARegisters.V7));
|
||||
case 8: return GetField(nameof(ARegisters.V8));
|
||||
case 9: return GetField(nameof(ARegisters.V9));
|
||||
case 10: return GetField(nameof(ARegisters.V10));
|
||||
case 11: return GetField(nameof(ARegisters.V11));
|
||||
case 12: return GetField(nameof(ARegisters.V12));
|
||||
case 13: return GetField(nameof(ARegisters.V13));
|
||||
case 14: return GetField(nameof(ARegisters.V14));
|
||||
case 15: return GetField(nameof(ARegisters.V15));
|
||||
case 16: return GetField(nameof(ARegisters.V16));
|
||||
case 17: return GetField(nameof(ARegisters.V17));
|
||||
case 18: return GetField(nameof(ARegisters.V18));
|
||||
case 19: return GetField(nameof(ARegisters.V19));
|
||||
case 20: return GetField(nameof(ARegisters.V20));
|
||||
case 21: return GetField(nameof(ARegisters.V21));
|
||||
case 22: return GetField(nameof(ARegisters.V22));
|
||||
case 23: return GetField(nameof(ARegisters.V23));
|
||||
case 24: return GetField(nameof(ARegisters.V24));
|
||||
case 25: return GetField(nameof(ARegisters.V25));
|
||||
case 26: return GetField(nameof(ARegisters.V26));
|
||||
case 27: return GetField(nameof(ARegisters.V27));
|
||||
case 28: return GetField(nameof(ARegisters.V28));
|
||||
case 29: return GetField(nameof(ARegisters.V29));
|
||||
case 30: return GetField(nameof(ARegisters.V30));
|
||||
case 31: return GetField(nameof(ARegisters.V31));
|
||||
}
|
||||
|
||||
throw new InvalidOperationException();
|
||||
}
|
||||
|
||||
private FieldInfo GetField(string Name)
|
||||
{
|
||||
return typeof(ARegisters).GetField(Name);
|
||||
}
|
||||
}
|
||||
}
|
10
Ryujinx/Cpu/State/ARegisterSize.cs
Normal file
10
Ryujinx/Cpu/State/ARegisterSize.cs
Normal file
|
@ -0,0 +1,10 @@
|
|||
namespace ChocolArm64.State
|
||||
{
|
||||
enum ARegisterSize
|
||||
{
|
||||
Int32,
|
||||
Int64,
|
||||
SIMD64,
|
||||
SIMD128
|
||||
}
|
||||
}
|
9
Ryujinx/Cpu/State/ARegisterType.cs
Normal file
9
Ryujinx/Cpu/State/ARegisterType.cs
Normal file
|
@ -0,0 +1,9 @@
|
|||
namespace ChocolArm64.State
|
||||
{
|
||||
enum ARegisterType
|
||||
{
|
||||
Flag,
|
||||
Int,
|
||||
Vector
|
||||
}
|
||||
}
|
126
Ryujinx/Cpu/State/ARegisters.cs
Normal file
126
Ryujinx/Cpu/State/ARegisters.cs
Normal file
|
@ -0,0 +1,126 @@
|
|||
using System;
|
||||
|
||||
namespace ChocolArm64.State
|
||||
{
|
||||
public class ARegisters
|
||||
{
|
||||
internal const int LRIndex = 30;
|
||||
internal const int ZRIndex = 31;
|
||||
|
||||
public ulong X0, X1, X2, X3, X4, X5, X6, X7,
|
||||
X8, X9, X10, X11, X12, X13, X14, X15,
|
||||
X16, X17, X18, X19, X20, X21, X22, X23,
|
||||
X24, X25, X26, X27, X28, X29, X30, X31;
|
||||
|
||||
public AVec V0, V1, V2, V3, V4, V5, V6, V7,
|
||||
V8, V9, V10, V11, V12, V13, V14, V15,
|
||||
V16, V17, V18, V19, V20, V21, V22, V23,
|
||||
V24, V25, V26, V27, V28, V29, V30, V31;
|
||||
|
||||
public bool Overflow;
|
||||
public bool Carry;
|
||||
public bool Zero;
|
||||
public bool Negative;
|
||||
|
||||
public int ProcessId;
|
||||
public int ThreadId;
|
||||
public long TlsAddrEl0;
|
||||
public long TlsAddr;
|
||||
|
||||
private int FPCR;
|
||||
private int FPSR;
|
||||
|
||||
public ACoreType CoreType;
|
||||
|
||||
private const ulong A53DczidEl0 = 4;
|
||||
private const ulong A53CtrEl0 = 0x84448004;
|
||||
private const ulong A57CtrEl0 = 0x8444c004;
|
||||
|
||||
private const ulong TicksPerS = 19_200_000;
|
||||
private const ulong TicksPerMS = TicksPerS / 1_000;
|
||||
|
||||
public event EventHandler<SvcEventArgs> SvcCall;
|
||||
public event EventHandler<EventArgs> Undefined;
|
||||
|
||||
public ulong GetSystemReg(int Op0, int Op1, int CRn, int CRm, int Op2)
|
||||
{
|
||||
switch (PackRegId(Op0, Op1, CRn, CRm, Op2))
|
||||
{
|
||||
case 0b11_011_0000_0000_001: return GetCtrEl0();
|
||||
case 0b11_011_0000_0000_111: return GetDczidEl0();
|
||||
case 0b11_011_0100_0100_000: return (ulong)PackFPCR();
|
||||
case 0b11_011_0100_0100_001: return (ulong)PackFPSR();
|
||||
case 0b11_011_1101_0000_010: return (ulong)TlsAddrEl0;
|
||||
case 0b11_011_1101_0000_011: return (ulong)TlsAddr;
|
||||
case 0b11_011_1110_0000_001: return (ulong)Environment.TickCount * TicksPerMS;
|
||||
|
||||
default: throw new ArgumentException();
|
||||
}
|
||||
}
|
||||
|
||||
public void SetSystemReg(int Op0, int Op1, int CRn, int CRm, int Op2, ulong Value)
|
||||
{
|
||||
switch (PackRegId(Op0, Op1, CRn, CRm, Op2))
|
||||
{
|
||||
case 0b11_011_0100_0100_000: UnpackFPCR((int)Value); break;
|
||||
case 0b11_011_0100_0100_001: UnpackFPSR((int)Value); break;
|
||||
case 0b11_011_1101_0000_010: TlsAddrEl0 = (long)Value; break;
|
||||
|
||||
default: throw new ArgumentException();
|
||||
}
|
||||
}
|
||||
|
||||
private int PackRegId(int Op0, int Op1, int CRn, int CRm, int Op2)
|
||||
{
|
||||
int Id;
|
||||
|
||||
Id = Op2 << 0;
|
||||
Id |= CRm << 3;
|
||||
Id |= CRn << 7;
|
||||
Id |= Op1 << 11;
|
||||
Id |= Op0 << 14;
|
||||
|
||||
return Id;
|
||||
}
|
||||
|
||||
public ulong GetCtrEl0()
|
||||
{
|
||||
return CoreType == ACoreType.CortexA53 ? A53CtrEl0 : A57CtrEl0;
|
||||
}
|
||||
|
||||
public ulong GetDczidEl0()
|
||||
{
|
||||
return A53DczidEl0;
|
||||
}
|
||||
|
||||
public int PackFPCR()
|
||||
{
|
||||
return FPCR; //TODO
|
||||
}
|
||||
|
||||
public int PackFPSR()
|
||||
{
|
||||
return FPSR; //TODO
|
||||
}
|
||||
|
||||
public void UnpackFPCR(int Value)
|
||||
{
|
||||
FPCR = Value;
|
||||
}
|
||||
|
||||
public void UnpackFPSR(int Value)
|
||||
{
|
||||
FPSR = Value;
|
||||
}
|
||||
|
||||
public void OnSvcCall(int Imm)
|
||||
{
|
||||
SvcCall?.Invoke(this, new SvcEventArgs(Imm));
|
||||
}
|
||||
|
||||
public void OnUndefined()
|
||||
{
|
||||
Undefined?.Invoke(this, EventArgs.Empty);
|
||||
}
|
||||
}
|
||||
}
|
243
Ryujinx/Cpu/State/AVec.cs
Normal file
243
Ryujinx/Cpu/State/AVec.cs
Normal file
|
@ -0,0 +1,243 @@
|
|||
using System;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace ChocolArm64.State
|
||||
{
|
||||
[StructLayout(LayoutKind.Explicit, Size = 16)]
|
||||
public struct AVec
|
||||
{
|
||||
[FieldOffset(0x0)] public byte B0;
|
||||
[FieldOffset(0x1)] public byte B1;
|
||||
[FieldOffset(0x2)] public byte B2;
|
||||
[FieldOffset(0x3)] public byte B3;
|
||||
[FieldOffset(0x4)] public byte B4;
|
||||
[FieldOffset(0x5)] public byte B5;
|
||||
[FieldOffset(0x6)] public byte B6;
|
||||
[FieldOffset(0x7)] public byte B7;
|
||||
[FieldOffset(0x8)] public byte B8;
|
||||
[FieldOffset(0x9)] public byte B9;
|
||||
[FieldOffset(0xa)] public byte B10;
|
||||
[FieldOffset(0xb)] public byte B11;
|
||||
[FieldOffset(0xc)] public byte B12;
|
||||
[FieldOffset(0xd)] public byte B13;
|
||||
[FieldOffset(0xe)] public byte B14;
|
||||
[FieldOffset(0xf)] public byte B15;
|
||||
|
||||
[FieldOffset(0x0)] public ushort H0;
|
||||
[FieldOffset(0x2)] public ushort H1;
|
||||
[FieldOffset(0x4)] public ushort H2;
|
||||
[FieldOffset(0x6)] public ushort H3;
|
||||
[FieldOffset(0x8)] public ushort H4;
|
||||
[FieldOffset(0xa)] public ushort H5;
|
||||
[FieldOffset(0xc)] public ushort H6;
|
||||
[FieldOffset(0xe)] public ushort H7;
|
||||
|
||||
[FieldOffset(0x0)] public uint W0;
|
||||
[FieldOffset(0x4)] public uint W1;
|
||||
[FieldOffset(0x8)] public uint W2;
|
||||
[FieldOffset(0xc)] public uint W3;
|
||||
|
||||
[FieldOffset(0x0)] public float S0;
|
||||
[FieldOffset(0x4)] public float S1;
|
||||
[FieldOffset(0x8)] public float S2;
|
||||
[FieldOffset(0xc)] public float S3;
|
||||
|
||||
[FieldOffset(0x0)] public ulong X0;
|
||||
[FieldOffset(0x8)] public ulong X1;
|
||||
|
||||
[FieldOffset(0x0)] public double D0;
|
||||
[FieldOffset(0x8)] public double D1;
|
||||
|
||||
public byte ExtractByte(int Index)
|
||||
{
|
||||
switch (Index)
|
||||
{
|
||||
case 0: return B0;
|
||||
case 1: return B1;
|
||||
case 2: return B2;
|
||||
case 3: return B3;
|
||||
case 4: return B4;
|
||||
case 5: return B5;
|
||||
case 6: return B6;
|
||||
case 7: return B7;
|
||||
case 8: return B8;
|
||||
case 9: return B9;
|
||||
case 10: return B10;
|
||||
case 11: return B11;
|
||||
case 12: return B12;
|
||||
case 13: return B13;
|
||||
case 14: return B14;
|
||||
case 15: return B15;
|
||||
}
|
||||
|
||||
throw new ArgumentOutOfRangeException(nameof(Index));
|
||||
}
|
||||
|
||||
public ushort ExtractUInt16(int Index)
|
||||
{
|
||||
switch (Index)
|
||||
{
|
||||
case 0: return H0;
|
||||
case 1: return H1;
|
||||
case 2: return H2;
|
||||
case 3: return H3;
|
||||
case 4: return H4;
|
||||
case 5: return H5;
|
||||
case 6: return H6;
|
||||
case 7: return H7;
|
||||
}
|
||||
|
||||
throw new ArgumentOutOfRangeException(nameof(Index));
|
||||
}
|
||||
|
||||
public uint ExtractUInt32(int Index)
|
||||
{
|
||||
switch (Index)
|
||||
{
|
||||
case 0: return W0;
|
||||
case 1: return W1;
|
||||
case 2: return W2;
|
||||
case 3: return W3;
|
||||
}
|
||||
|
||||
throw new ArgumentOutOfRangeException(nameof(Index));
|
||||
}
|
||||
|
||||
public float ExtractSingle(int Index)
|
||||
{
|
||||
switch (Index)
|
||||
{
|
||||
case 0: return S0;
|
||||
case 1: return S1;
|
||||
case 2: return S2;
|
||||
case 3: return S3;
|
||||
}
|
||||
|
||||
throw new ArgumentOutOfRangeException(nameof(Index));
|
||||
}
|
||||
|
||||
public ulong ExtractUInt64(int Index)
|
||||
{
|
||||
switch (Index)
|
||||
{
|
||||
case 0: return X0;
|
||||
case 1: return X1;
|
||||
}
|
||||
|
||||
throw new ArgumentOutOfRangeException(nameof(Index));
|
||||
}
|
||||
|
||||
public double ExtractDouble(int Index)
|
||||
{
|
||||
switch (Index)
|
||||
{
|
||||
case 0: return D0;
|
||||
case 1: return D1;
|
||||
}
|
||||
|
||||
throw new ArgumentOutOfRangeException(nameof(Index));
|
||||
}
|
||||
|
||||
public static AVec InsertByte(AVec Vec, int Index, byte Value)
|
||||
{
|
||||
switch (Index)
|
||||
{
|
||||
case 0: Vec.B0 = Value; break;
|
||||
case 1: Vec.B1 = Value; break;
|
||||
case 2: Vec.B2 = Value; break;
|
||||
case 3: Vec.B3 = Value; break;
|
||||
case 4: Vec.B4 = Value; break;
|
||||
case 5: Vec.B5 = Value; break;
|
||||
case 6: Vec.B6 = Value; break;
|
||||
case 7: Vec.B7 = Value; break;
|
||||
case 8: Vec.B8 = Value; break;
|
||||
case 9: Vec.B9 = Value; break;
|
||||
case 10: Vec.B10 = Value; break;
|
||||
case 11: Vec.B11 = Value; break;
|
||||
case 12: Vec.B12 = Value; break;
|
||||
case 13: Vec.B13 = Value; break;
|
||||
case 14: Vec.B14 = Value; break;
|
||||
case 15: Vec.B15 = Value; break;
|
||||
|
||||
default: throw new ArgumentOutOfRangeException(nameof(Index));
|
||||
}
|
||||
|
||||
return Vec;
|
||||
}
|
||||
|
||||
public static AVec InsertUInt16(AVec Vec, int Index, ushort Value)
|
||||
{
|
||||
switch (Index)
|
||||
{
|
||||
case 0: Vec.H0 = Value; break;
|
||||
case 1: Vec.H1 = Value; break;
|
||||
case 2: Vec.H2 = Value; break;
|
||||
case 3: Vec.H3 = Value; break;
|
||||
case 4: Vec.H4 = Value; break;
|
||||
case 5: Vec.H5 = Value; break;
|
||||
case 6: Vec.H6 = Value; break;
|
||||
case 7: Vec.H7 = Value; break;
|
||||
|
||||
default: throw new ArgumentOutOfRangeException(nameof(Index));
|
||||
}
|
||||
|
||||
return Vec;
|
||||
}
|
||||
|
||||
public static AVec InsertUInt32(AVec Vec, int Index, uint Value)
|
||||
{
|
||||
switch (Index)
|
||||
{
|
||||
case 0: Vec.W0 = Value; break;
|
||||
case 1: Vec.W1 = Value; break;
|
||||
case 2: Vec.W2 = Value; break;
|
||||
case 3: Vec.W3 = Value; break;
|
||||
|
||||
default: throw new ArgumentOutOfRangeException(nameof(Index));
|
||||
}
|
||||
|
||||
return Vec;
|
||||
}
|
||||
|
||||
public static AVec InsertSingle(AVec Vec, int Index, float Value)
|
||||
{
|
||||
switch (Index)
|
||||
{
|
||||
case 0: Vec.S0 = Value; break;
|
||||
case 1: Vec.S1 = Value; break;
|
||||
case 2: Vec.S2 = Value; break;
|
||||
case 3: Vec.S3 = Value; break;
|
||||
|
||||
default: throw new ArgumentOutOfRangeException(nameof(Index));
|
||||
}
|
||||
|
||||
return Vec;
|
||||
}
|
||||
|
||||
public static AVec InsertUInt64(AVec Vec, int Index, ulong Value)
|
||||
{
|
||||
switch (Index)
|
||||
{
|
||||
case 0: Vec.X0 = Value; break;
|
||||
case 1: Vec.X1 = Value; break;
|
||||
|
||||
default: throw new ArgumentOutOfRangeException(nameof(Index));
|
||||
}
|
||||
|
||||
return Vec;
|
||||
}
|
||||
|
||||
public static AVec InsertDouble(AVec Vec, int Index, double Value)
|
||||
{
|
||||
switch (Index)
|
||||
{
|
||||
case 0: Vec.D0 = Value; break;
|
||||
case 1: Vec.D1 = Value; break;
|
||||
|
||||
default: throw new ArgumentOutOfRangeException(nameof(Index));
|
||||
}
|
||||
|
||||
return Vec;
|
||||
}
|
||||
}
|
||||
}
|
14
Ryujinx/Cpu/State/SvcEventArgs.cs
Normal file
14
Ryujinx/Cpu/State/SvcEventArgs.cs
Normal file
|
@ -0,0 +1,14 @@
|
|||
using System;
|
||||
|
||||
namespace ChocolArm64.State
|
||||
{
|
||||
public class SvcEventArgs : EventArgs
|
||||
{
|
||||
public int Id { get; private set; }
|
||||
|
||||
public SvcEventArgs(int Id)
|
||||
{
|
||||
this.Id = Id;
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue