Use SysAD pins instead of passing maps.

master
Nabile Rahmani 2017-11-21 12:59:59 +01:00
parent f20f931b12
commit a6ae17a345
6 changed files with 41 additions and 33 deletions

View File

@ -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
}

View File

@ -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
}
}

View File

@ -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))
{

View File

@ -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
}

View File

@ -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" : "-")}";

View File

@ -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