DotN64/DotN64/RCP/MI/RealityCoprocessor.MIPSInte...

127 lines
4.7 KiB
C#

using System.Collections.Specialized;
namespace DotN64.RCP
{
using CPU;
public partial class RealityCoprocessor
{
public partial class MIPSInterface : Interface
{
#region Properties
private VR4300 CPU => rcp.nintendo64.CPU;
public InitModeRegister InitMode { get; set; }
public VersionRegister Version { get; set; } = VersionRegister.Version2;
public Interrupts InterruptMask { get; set; }
private Interrupts interrupt;
public Interrupts Interrupt
{
get => interrupt;
set
{
interrupt = value;
UpdateInterrupt();
}
}
#endregion
#region Constructors
public MIPSInterface(RealityCoprocessor rcp)
: base(rcp)
{
MemoryMaps = new[]
{
new MappingEntry(0x04300000, 0x04300003) // MI init mode.
{
Write = (o, d) =>
{
var bits = new BitVector32((int)d);
var mode = InitMode;
mode.InitLength = (byte)bits[InitModeRegister.InitLengthSection];
mode.InitMode &= bits[InitModeRegister.ClearInitModeSection] == 0;
mode.InitMode |= bits[InitModeRegister.SetInitModeSection] != 0;
mode.EBusTestMode &= bits[InitModeRegister.ClearEBusTestModeSection] == 0;
mode.EBusTestMode |= bits[InitModeRegister.SetEBusTestModeSection] != 0;
if (bits[InitModeRegister.ClearDPInterruptSection] != 0)
Interrupt &= ~Interrupts.DP;
mode.RDRAMRegMode &= bits[InitModeRegister.ClearRDRAMRegSection] == 0;
mode.RDRAMRegMode |= bits[InitModeRegister.SetRDRAMRegModeSection] != 0;
InitMode = mode;
}
},
new MappingEntry(0x04300004, 0x04300007) // MI version.
{
Read = o => Version
},
new MappingEntry(0x04300008, 0x0430000B) // MI interrupt.
{
Read = o => (uint)Interrupt
},
new MappingEntry(0x0430000C, 0x0430000F) // MI interrupt mask.
{
Read = o => (uint)InterruptMask,
Write = (o, d) =>
{
var mask = (InterruptMaskWrites)d;
void Clear(InterruptMaskWrites clearMask, Interrupts interrupt)
{
if ((mask & clearMask) != 0)
InterruptMask &= ~interrupt;
}
void Set(InterruptMaskWrites setMask, Interrupts interrupt)
{
if ((mask & setMask) != 0)
InterruptMask |= interrupt;
}
Clear(InterruptMaskWrites.ClearSP, Interrupts.SP);
Set(InterruptMaskWrites.SetSP, Interrupts.SP);
Clear(InterruptMaskWrites.ClearSI, Interrupts.SI);
Set(InterruptMaskWrites.SetSI, Interrupts.SI);
Clear(InterruptMaskWrites.ClearAI, Interrupts.AI);
Set(InterruptMaskWrites.SetAI, Interrupts.AI);
Clear(InterruptMaskWrites.ClearVI, Interrupts.VI);
Set(InterruptMaskWrites.SetVI, Interrupts.VI);
Clear(InterruptMaskWrites.ClearPI, Interrupts.PI);
Set(InterruptMaskWrites.SetPI, Interrupts.PI);
Clear(InterruptMaskWrites.ClearDP, Interrupts.DP);
Set(InterruptMaskWrites.SetDP, Interrupts.DP);
UpdateInterrupt();
}
}
};
}
#endregion
#region Methods
private void UpdateInterrupt()
{
if ((Interrupt & InterruptMask) != 0)
CPU.Int |= (byte)InterruptPins.RCP;
else
CPU.Int &= (byte)~InterruptPins.RCP;
}
#endregion
}
}
}