Ryujinx/ChocolArm64/State/CpuThreadState.cs
gdkchan a694420d11
Implement speculative translation on the CPU (#515)
* Implement speculative translation on the cpu, and change the way how branches to unknown or untranslated addresses works

* Port t0opt changes and other cleanups

* Change namespace from translation related classes to ChocolArm64.Translation, other minor tweaks

* Fix typo

* Translate higher quality code for indirect jumps aswell, and on some cases that were missed when lower quality (tier 0) code was available

* Remove debug print

* Remove direct argument passing optimization, and enable tail calls for BR instructions

* Call delegates directly with Callvirt rather than calling Execute, do not emit calls for tier 0 code

* Remove unused property

* Rename argument on ArmSubroutine delegate
2019-02-04 18:26:05 -03:00

172 lines
4.6 KiB
C#

using ChocolArm64.Events;
using ChocolArm64.Translation;
using System;
using System.Diagnostics;
using System.Runtime.CompilerServices;
using System.Runtime.Intrinsics;
namespace ChocolArm64.State
{
public class CpuThreadState
{
internal const int ErgSizeLog2 = 4;
internal const int DczSizeLog2 = 4;
private const int MinInstForCheck = 4000000;
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 Vector128<float> 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 Aarch32;
public bool Thumb;
public bool BigEndian;
public bool Overflow;
public bool Carry;
public bool Zero;
public bool Negative;
public int ElrHyp;
public bool Running { get; set; }
public int Core { get; set; }
private bool _interrupted;
private int _syncCount;
public long TpidrEl0 { get; set; }
public long Tpidr { get; set; }
public int Fpcr { get; set; }
public int Fpsr { get; set; }
public int Psr
{
get
{
return (Negative ? (int)PState.NMask : 0) |
(Zero ? (int)PState.ZMask : 0) |
(Carry ? (int)PState.CMask : 0) |
(Overflow ? (int)PState.VMask : 0);
}
}
public uint CtrEl0 => 0x8444c004;
public uint DczidEl0 => 0x00000004;
public ulong CntfrqEl0 { get; set; }
public ulong CntpctEl0
{
get
{
double ticks = _tickCounter.ElapsedTicks * _hostTickFreq;
return (ulong)(ticks * CntfrqEl0);
}
}
public event EventHandler<EventArgs> Interrupt;
public event EventHandler<InstExceptionEventArgs> Break;
public event EventHandler<InstExceptionEventArgs> SvcCall;
public event EventHandler<InstUndefinedEventArgs> Undefined;
private static Stopwatch _tickCounter;
private static double _hostTickFreq;
internal Translator CurrentTranslator;
static CpuThreadState()
{
_hostTickFreq = 1.0 / Stopwatch.Frequency;
_tickCounter = new Stopwatch();
_tickCounter.Start();
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
internal bool Synchronize(int bbWeight)
{
//Firing a interrupt frequently is expensive, so we only
//do it after a given number of instructions has executed.
_syncCount += bbWeight;
if (_syncCount >= MinInstForCheck)
{
CheckInterrupt();
}
return Running;
}
internal void RequestInterrupt()
{
_interrupted = true;
}
[MethodImpl(MethodImplOptions.NoInlining)]
private void CheckInterrupt()
{
_syncCount = 0;
if (_interrupted)
{
_interrupted = false;
Interrupt?.Invoke(this, EventArgs.Empty);
}
}
internal void OnBreak(long position, int imm)
{
Break?.Invoke(this, new InstExceptionEventArgs(position, imm));
}
internal void OnSvcCall(long position, int imm)
{
SvcCall?.Invoke(this, new InstExceptionEventArgs(position, imm));
}
internal void OnUndefined(long position, int rawOpCode)
{
Undefined?.Invoke(this, new InstUndefinedEventArgs(position, rawOpCode));
}
internal ExecutionMode GetExecutionMode()
{
if (!Aarch32)
{
return ExecutionMode.Aarch64;
}
else
{
return Thumb ? ExecutionMode.Aarch32Thumb : ExecutionMode.Aarch32Arm;
}
}
internal bool GetFpcrFlag(Fpcr flag)
{
return (Fpcr & (1 << (int)flag)) != 0;
}
internal void SetFpsrFlag(Fpsr flag)
{
Fpsr |= 1 << (int)flag;
}
internal RoundMode FPRoundingMode()
{
return (RoundMode)((Fpcr >> (int)State.Fpcr.RMode) & 3);
}
}
}