C#C
C#14mo ago
Pdawg

Micro-optimizing a Z80 emulators' pipeline. **Unsafe code**

so, i'm writing an emulator, and i'm trying to squeeze as much perf as i can out of hot paths. this seemingly simple fetch operation consumes about a third of the CPU time:
private byte Fetch()
{
    return _memory.Read(Registers.PC++);
}


my memory class looks like this:
private GCHandle _memHandle;
private byte* pMem;
private byte[] _memory;

public MainMemory(int size) 
{
    // pin array and get GC ptr. omitted for brevity.
    pMem = (byte*)_memHandle.AddrOfPinnedObject();
}

[MethodImpl(MethodImplOptions.AggressiveInlining)]
public byte Read(ushort address) => pMem[address];

i know, it's a bit messy, and it's not really safe either, but boy does it give some perf gains. it's worth it. also, the array wont change size so it should be alright.

my registers are in a similar situation. the register set is actually an array of bytes that are accessed using constant indexers into said array, like this:
private GCHandle _regSetHandle;
private byte* pRegSet;
public byte[] RegisterSet;
public ProcessorRegisters()
{
    RegisterSet = new byte[26];
    _regSetHandle = GCHandle.Alloc(RegisterSet, GCHandleType.Pinned);
    pRegSet = (byte*)_regSetHandle.AddrOfPinnedObject();
}
// example
byte regA = pRegSet[Registers.A]; // A is an indexer into the array; i tried to follow the Z80's convention, so A = 7


but, this is a Z80, meaning it also has 16-bit register pairs. this is important, because you can either access it as its high and low parts, or its entire pair, meaning that the exposed pairs depend on this same array, so i implemented them using properties
public ushort PC
{
    get => (ushort)((pRegSet[PCi] << 8) | pRegSet[PCiL]);
    set
    {
        pRegSet[PCi] = (byte)(value >> 8);
        pRegSet[PCiL] = (byte)value;
    }
}


with all of this in mind, how can i make that fetch instruction faster and use less CPU time?
Was this page helpful?
Micro-optimizing a Z80 emulators' pipeline. **Unsafe code** - C#