DotN64/DotN64/CPU/VR4300/CP0/VR4300.SystemControlUnit.Ca...

159 lines
6.9 KiB
C#

using System;
using System.Collections.Specialized;
namespace DotN64.CPU
{
public partial class VR4300
{
public partial class SystemControlUnit
{
/// <summary>
/// See: datasheet#6.3.6.
/// </summary>
public class CauseRegister : Register
{
#region Fields
private static readonly BitVector32.Section constant0 = BitVector32.CreateSection((1 << 2) - 1),
excCode = BitVector32.CreateSection((1 << 5) - 1, constant0),
constant1 = BitVector32.CreateSection(1, excCode),
ip = BitVector32.CreateSection((1 << 8) - 1, constant1),
constant2 = BitVector32.CreateSection((1 << 12) - 1, ip),
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
/// <summary>
/// Exception code field (refer to Table 6-2 for details.)
/// </summary>
public ExceptionCode ExcCode
{
get => (ExceptionCode)this[excCode];
set => this[excCode] = (byte)value;
}
/// <summary>
/// Indicates an interrupt is pending.
/// 1 → interrupt pending
/// 0 → no interrupt
/// IP(7) : Timer interrupt
/// IP(6:2) : External normal interrupts. Controlled by Int[4:0], or external write requests
/// IP(1:0) : Software interrupts. Only these bits can cause interrupt exception when they are set to 1 by software.
/// </summary>
public InterruptPending IP
{
get => (InterruptPending)this[ip];
set => this[ip] = value;
}
/// <summary>
/// Coprocessor unit number referenced when a Coprocessor Unusable exception has occurred.
/// If this exception does not occur, undefined.
/// </summary>
public byte CE
{
get => (byte)this[ce];
set => this[ce] = value;
}
/// <summary>
/// Indicates whether the last exception occurred has been executed in a branch delay slot.
/// 1 → delay slot
/// 0 → normal
/// </summary>
public bool BD
{
get => Convert.ToBoolean(this[bd]);
set => this[bd] = Convert.ToInt32(value);
}
#endregion
#region Constructors
public CauseRegister(SystemControlUnit cp0)
: base(cp0, RegisterIndex.Cause) { }
#endregion
#region Structures
public struct InterruptPending
{
#region Fields
private BitVector32 bits;
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
public byte SoftwareInterrupts
{
get => (byte)bits[softwareInterrupts];
set => bits[softwareInterrupts] = value;
}
public byte ExternalNormalInterrupts
{
get => (byte)bits[externalNormalInterrupts];
set => bits[externalNormalInterrupts] = value;
}
public bool TimerInterrupt
{
get => Convert.ToBoolean(bits[timerInterrupt]);
set => bits[timerInterrupt] = Convert.ToInt32(value);
}
#endregion
#region Operators
public static implicit operator InterruptPending(byte data) => new InterruptPending { bits = new BitVector32(data) };
public static implicit operator byte(InterruptPending interrupt) => (byte)interrupt.bits.Data;
#endregion
}
#endregion
#region Enumerations
public enum ExceptionCode : byte
{
/// <summary>Interrupt.</summary>
Int = 0,
/// <summary>TLB Modification exception.</summary>
Mod = 1,
/// <summary>TLB Miss exception (load or instruction fetch).</summary>
TLBL = 2,
/// <summary>TLB Miss exception (store).</summary>
TLBS = 3,
/// <summary>Address Error exception (load or instruction fetch).</summary>
AdEL = 4,
/// <summary>Address Error exception (store).</summary>
AdES = 5,
/// <summary>Bus Error exception (instruction fetch).</summary>
IBE = 6,
/// <summary>Bus Error exception (data reference: load or store).</summary>
DBE = 7,
/// <summary>Syscall exception.</summary>
Sys = 8,
/// <summary>Breakpoint exception.</summary>
Bp = 9,
/// <summary>Reserved Instruction exception.</summary>
RI = 10,
/// <summary>Coprocessor Unusable exception.</summary>
CpU = 11,
/// <summary>Arithmetic Overflow exception.</summary>
Ov = 12,
/// <summary>Trap exception.</summary>
Tr = 13,
/// <summary>Floating-Point exception.</summary>
FPE = 15,
/// <summary>Watch exception.</summary>
WATCH = 23
}
#endregion
}
}
}
}