Use SysAD pins instead of passing maps.
parent
f20f931b12
commit
a6ae17a345
|
@ -1,18 +1,11 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace DotN64.CPU
|
||||
{
|
||||
using Extensions;
|
||||
|
||||
public partial class VR4300
|
||||
{
|
||||
public partial class SystemControlUnit
|
||||
{
|
||||
#region Fields
|
||||
private readonly IReadOnlyList<MappingEntry> memoryMaps;
|
||||
#endregion
|
||||
|
||||
#region Properties
|
||||
public ulong[] Registers { get; } = new ulong[32];
|
||||
|
||||
|
@ -22,9 +15,8 @@ namespace DotN64.CPU
|
|||
#endregion
|
||||
|
||||
#region Constructors
|
||||
public SystemControlUnit(IReadOnlyList<MappingEntry> memoryMaps)
|
||||
public SystemControlUnit()
|
||||
{
|
||||
this.memoryMaps = memoryMaps;
|
||||
Config = new ConfigRegister(this);
|
||||
Status = new StatusRegister(this);
|
||||
}
|
||||
|
@ -35,23 +27,17 @@ namespace DotN64.CPU
|
|||
/// Translates a virtual address into a physical address.
|
||||
/// See: datasheet#5.2.4 Table 5-3.
|
||||
/// </summary>
|
||||
/// <param name="address">The virtual address to translate into a physical address.</param>
|
||||
/// <returns>The memory map entry associated with the address.</returns>
|
||||
public MappingEntry Map(ref ulong address)
|
||||
public ulong Map(ulong address)
|
||||
{
|
||||
switch (address >> 29 & 0b111)
|
||||
{
|
||||
case 0b100: // kseg0.
|
||||
address -= 0xFFFFFFFF80000000;
|
||||
break;
|
||||
return address - 0xFFFFFFFF80000000;
|
||||
case 0b101: // kseg1.
|
||||
address -= 0xFFFFFFFFA0000000;
|
||||
break;
|
||||
return address - 0xFFFFFFFFA0000000;
|
||||
default:
|
||||
throw new Exception($"Unknown memory map segment for location 0x{address:X}.");
|
||||
throw new Exception($"Unknown memory map segment for location 0x{address:X16}.");
|
||||
}
|
||||
|
||||
return memoryMaps.GetEntry(address);
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Runtime.CompilerServices;
|
||||
|
||||
namespace DotN64.CPU
|
||||
{
|
||||
|
@ -60,8 +61,6 @@ namespace DotN64.CPU
|
|||
/// </summary>
|
||||
public float FCR31 { get; set; }
|
||||
|
||||
public SystemControlUnit CP0 { get; }
|
||||
|
||||
private byte divMode;
|
||||
/// <summary>
|
||||
/// Internal operating frequency mode.
|
||||
|
@ -73,13 +72,24 @@ namespace DotN64.CPU
|
|||
set => divMode = (byte)(value & ((1 << 2) - 1));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// System address/data bus.
|
||||
/// </summary>
|
||||
public Func<ulong, uint> ReadSysAD { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// System address/data bus.
|
||||
/// </summary>
|
||||
public Action<ulong, uint> WriteSysAD { get; set; }
|
||||
|
||||
public SystemControlUnit CP0 { get; } = new SystemControlUnit();
|
||||
|
||||
public ulong? DelaySlot { get; private set; }
|
||||
#endregion
|
||||
|
||||
#region Constructors
|
||||
public VR4300(IReadOnlyList<MappingEntry> memoryMaps)
|
||||
public VR4300()
|
||||
{
|
||||
CP0 = new SystemControlUnit(memoryMaps);
|
||||
operations = new Dictionary<OpCode, Action<Instruction>>
|
||||
{
|
||||
[OpCode.SPECIAL] = i =>
|
||||
|
@ -87,14 +97,14 @@ namespace DotN64.CPU
|
|||
if (specialOperations.TryGetValue((SpecialOpCode)i.Funct, out var operation))
|
||||
operation(i);
|
||||
else
|
||||
throw new Exception($"Unknown special opcode (0b{Convert.ToString(i.Funct, 2)}) from instruction 0x{(uint)i:X}.");
|
||||
throw new Exception($"Unknown special opcode (0b{Convert.ToString(i.Funct, 2)}) from instruction 0x{(uint)i:X8}.");
|
||||
},
|
||||
[OpCode.REGIMM] = i =>
|
||||
{
|
||||
if (regImmOperations.TryGetValue((RegImmOpCode)i.RT, out var operation))
|
||||
operation(i);
|
||||
else
|
||||
throw new Exception($"Unknown reg imm opcode (0b{Convert.ToString(i.RT, 2)}) from instruction 0x{(uint)i:X}.");
|
||||
throw new Exception($"Unknown reg imm opcode (0b{Convert.ToString(i.RT, 2)}) from instruction 0x{(uint)i:X8}.");
|
||||
},
|
||||
[OpCode.LUI] = i => GPR[i.RT] = (ulong)(i.Immediate << 16),
|
||||
[OpCode.MTC0] = i => CP0.Registers[i.RD] = GPR[i.RT],
|
||||
|
@ -173,7 +183,7 @@ namespace DotN64.CPU
|
|||
if (operations.TryGetValue(instruction.OP, out var operation))
|
||||
operation(instruction);
|
||||
else
|
||||
throw new Exception($"Unknown opcode (0b{Convert.ToString((byte)instruction.OP, 2)}) from instruction 0x{(uint)instruction:X}.");
|
||||
throw new Exception($"Unknown opcode (0b{Convert.ToString((byte)instruction.OP, 2)}) from instruction 0x{(uint)instruction:X8}.");
|
||||
}
|
||||
|
||||
public void Step()
|
||||
|
@ -216,9 +226,11 @@ namespace DotN64.CPU
|
|||
PC += Instruction.Size;
|
||||
}
|
||||
|
||||
private uint ReadWord(ulong address) => CP0.Map(ref address).ReadWord(address);
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
private uint ReadWord(ulong address) => ReadSysAD(CP0.Map(address));
|
||||
|
||||
private void WriteWord(ulong address, uint value) => CP0.Map(ref address).WriteWord(address, value);
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
private void WriteWord(ulong address, uint value) => WriteSysAD(CP0.Map(address), value);
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,6 +6,7 @@ using System.Linq;
|
|||
namespace DotN64.Diagnostics
|
||||
{
|
||||
using CPU;
|
||||
using Extensions;
|
||||
|
||||
public partial class Debugger
|
||||
{
|
||||
|
@ -154,8 +155,8 @@ namespace DotN64.Diagnostics
|
|||
if (!address.HasValue)
|
||||
address = nintendo64.CPU.DelaySlot ?? nintendo64.CPU.PC;
|
||||
|
||||
var physicalAddress = address.Value;
|
||||
var instruction = nintendo64.CPU.CP0.Map(ref physicalAddress).ReadWord(physicalAddress);
|
||||
var physicalAddress = nintendo64.CPU.CP0.Map(address.Value);
|
||||
var instruction = nintendo64.MemoryMaps.GetEntry(physicalAddress).ReadWord(physicalAddress);
|
||||
|
||||
if (labels.ContainsKey(address.Value))
|
||||
{
|
||||
|
|
|
@ -1,11 +1,13 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Runtime.CompilerServices;
|
||||
|
||||
namespace DotN64.Extensions
|
||||
{
|
||||
public static class MappingEntryExtensions
|
||||
{
|
||||
#region Methods
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static MappingEntry GetEntry(this IReadOnlyList<MappingEntry> memoryMaps, ulong address)
|
||||
{
|
||||
for (int i = 0; i < memoryMaps.Count; i++)
|
||||
|
@ -16,7 +18,7 @@ namespace DotN64.Extensions
|
|||
return entry;
|
||||
}
|
||||
|
||||
throw new Exception($"Unknown physical address: 0x{address:X}.");
|
||||
throw new Exception($"Unknown physical address: 0x{address:X16}.");
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
using System;
|
||||
using System.Runtime.CompilerServices;
|
||||
|
||||
namespace DotN64
|
||||
{
|
||||
|
@ -27,10 +28,13 @@ namespace DotN64
|
|||
#endregion
|
||||
|
||||
#region Methods
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public bool Contains(ulong address) => address >= StartAddress && address <= EndAddress;
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public uint ReadWord(ulong address) => Read(OffsetAddress ? address - StartAddress : address);
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public void WriteWord(ulong address, uint value) => Write(OffsetAddress ? address - StartAddress : address, value);
|
||||
|
||||
public override string ToString() => $"[0x{StartAddress:X16}..0x{EndAddress:X16}] - {(Read != null ? "R" : "-")}{(Write != null ? "W" : "-")}";
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
namespace DotN64
|
||||
{
|
||||
using CPU;
|
||||
using Extensions;
|
||||
using RCP;
|
||||
|
||||
public class Nintendo64
|
||||
|
@ -85,9 +86,11 @@ namespace DotN64
|
|||
Write = RCP.RI.WriteWord
|
||||
}
|
||||
};
|
||||
CPU = new VR4300(MemoryMaps)
|
||||
CPU = new VR4300
|
||||
{
|
||||
DivMode = 0b01 // Assuming this value as the CPU is clocked at 93.75 MHz, and the RCP would be clocked at 93.75 / 3 * 2 = 62.5 MHz.
|
||||
DivMode = 0b01, // Assuming this value as the CPU is clocked at 93.75 MHz, and the RCP would be clocked at 93.75 / 3 * 2 = 62.5 MHz.
|
||||
ReadSysAD = a => MemoryMaps.GetEntry(a).ReadWord(a),
|
||||
WriteSysAD = (a, v) => MemoryMaps.GetEntry(a).WriteWord(a, v)
|
||||
};
|
||||
}
|
||||
#endregion
|
||||
|
|
Loading…
Reference in New Issue