Refactored CP0 stuff.

master
Nabile Rahmani 2018-06-05 20:44:13 +02:00
parent 05cf22619a
commit dca7725258
2 changed files with 22 additions and 7 deletions

View File

@ -1,5 +1,6 @@
using System;
using System.Collections.Generic;
using System.Runtime.CompilerServices;
namespace DotN64.CPU
{
@ -21,6 +22,8 @@ namespace DotN64.CPU
public StatusRegister Status { get; }
public CauseRegister Cause { get; }
public bool HasPendingInterrupt => Status.IE && !(Status.EXL | Status.ERL) && (Status.IM & Cause.IP) != 0;
#endregion
#region Constructors
@ -66,10 +69,25 @@ namespace DotN64.CPU
#endregion
#region Methods
/// <summary>
/// Increments the Count register (must be called on every odd PClock cycle), and updates the timer interrupt.
/// </summary>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void IncrementCounter()
{
if ((uint)++Registers[(int)RegisterIndex.Count] == (uint)Registers[(int)RegisterIndex.Compare])
{
var ip = Cause.IP;
ip.TimerInterrupt = true;
Cause.IP = ip;
}
}
/// <summary>
/// Translates a virtual address into a physical address.
/// See: datasheet#5.2.4 Table 5-3.
/// </summary>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public uint Translate(ulong address)
{
switch (address >> 29 & 0b111)
@ -83,8 +101,10 @@ namespace DotN64.CPU
}
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public bool IsCoprocessorUsable(byte unit) => ((byte)Status.CU & 1 << unit) != 0 || (unit == 0 && Status.KSU == StatusRegister.Mode.Kernel);
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void Run(Instruction instruction)
{
if (operations.TryGetValue((OpCode)instruction.RS, out var operation))

View File

@ -277,14 +277,9 @@ namespace DotN64.CPU
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void Cycle()
{
if ((uint)++CP0.Registers[(int)SystemControlUnit.RegisterIndex.Count] == (uint)CP0.Registers[(int)SystemControlUnit.RegisterIndex.Compare])
{
var ip = CP0.Cause.IP;
ip.TimerInterrupt = true;
CP0.Cause.IP = ip;
}
CP0.IncrementCounter();
if (CP0.Status.IE && !CP0.Status.EXL && !CP0.Status.ERL && (CP0.Status.IM & CP0.Cause.IP) != 0)
if (CP0.HasPendingInterrupt)
{
ExceptionProcessing.Interrupt(this);
return;