Skip to content

Commit

Permalink
Handle special cases for CP0 register writes.
Browse files Browse the repository at this point in the history
- The timer interrupt is cleared on writes to the Compare register (see: #6.3.4).
- Only software interrupt bits are writable into the Cause register (see: #6.3.6).
  • Loading branch information
Nabile-Rahmani committed Dec 24, 2018
1 parent bb4d756 commit a4d06ce
Show file tree
Hide file tree
Showing 2 changed files with 23 additions and 2 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ public class CauseRegister : Register
ce = BitVector32.CreateSection((1 << 2) - 1, constant2),
constant3 = BitVector32.CreateSection(1, ce),
bd = BitVector32.CreateSection(1, constant3);
public static readonly ulong WriteMask = (ulong)(InterruptPending.WriteMask << ip.Offset);
#endregion

#region Properties
Expand Down Expand Up @@ -80,9 +81,10 @@ public struct InterruptPending
#region Fields
private BitVector32 bits;

private static BitVector32.Section softwareInterrupts = BitVector32.CreateSection((1 << 2) - 1),
private static readonly BitVector32.Section softwareInterrupts = BitVector32.CreateSection((1 << 2) - 1),
externalNormalInterrupts = BitVector32.CreateSection((1 << 5) - 1, softwareInterrupts),
timerInterrupt = BitVector32.CreateSection(1, externalNormalInterrupts);
public static readonly byte WriteMask = (byte)(softwareInterrupts.Mask << softwareInterrupts.Offset);
#endregion

#region Properties
Expand Down
21 changes: 20 additions & 1 deletion DotN64/CPU/VR4300/CP0/VR4300.SystemControlUnit.cs
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,26 @@ public SystemControlUnit(VR4300 cpu)
Cause = new CauseRegister(this);
operations = new Dictionary<Instruction, Action<Instruction>>
{
[From(OpCode.MT)] = i => Registers[i.RD] = cpu.GPR[i.RT],
[From(OpCode.MT)] = i =>
{
var destination = i.RD;
var data = cpu.GPR[i.RT];

switch ((RegisterIndex)destination)
{
case RegisterIndex.Cause:
Registers[destination] &= ~CauseRegister.WriteMask;
Registers[destination] |= data & CauseRegister.WriteMask;
return;
case RegisterIndex.Compare:
var ip = Cause.IP;
ip.TimerInterrupt = false;
Cause.IP = ip;
break;
}

Registers[destination] = data;
},
[From(OpCode.MF)] = i => cpu.GPR[i.RT] = (ulong)(int)Registers[i.RD],
[From(FunctOpCode.TLBWI)] = i => { /* TODO. */ },
[From(FunctOpCode.ERET)] = i =>
Expand Down

0 comments on commit a4d06ce

Please sign in to comment.