Some performance improvements. About 50Mhz for Z80 emulator. 275Mhz to 325Mhz. Interesting.

This commit is contained in:
Adrian Conlon committed 2026-05-16 11:09:03 +01:00
1 parent b5f646c641
commit e0fffdaa5e
9 files changed
+77 -58

No files matched your search

+8 -8
View File
@@ -14,21 +14,21 @@ namespace EightBit
public override void PokeWord(ushort address, Register16 value)
{
ArgumentNullException.ThrowIfNull(value);
//ArgumentNullException.ThrowIfNull(value);
this.Bus.Poke(address, value.High);
this.Bus.Poke(++address, value.Low);
}
protected override void FetchInto(Register16 into)
{
ArgumentNullException.ThrowIfNull(into);
//ArgumentNullException.ThrowIfNull(into);
into.High = this.FetchByte();
into.Low = this.FetchByte();
}
protected override void GetInto(Register16 into)
{
ArgumentNullException.ThrowIfNull(into);
//ArgumentNullException.ThrowIfNull(into);
into.High = this.MemoryRead();
this.Bus.Address.Increment();
into.Low = this.MemoryRead();
@@ -36,7 +36,7 @@ namespace EightBit
protected override void GetPagedInto(Register16 into)
{
ArgumentNullException.ThrowIfNull(into);
//ArgumentNullException.ThrowIfNull(into);
into.High = this.MemoryRead();
++this.Bus.Address.Low;
into.Low = this.MemoryRead();
@@ -44,21 +44,21 @@ namespace EightBit
protected override void PopInto(Register16 into)
{
ArgumentNullException.ThrowIfNull(into);
//ArgumentNullException.ThrowIfNull(into);
into.High = this.Pop();
into.Low = this.Pop();
}
protected override void PushWord(Register16 value)
{
ArgumentNullException.ThrowIfNull(value);
//ArgumentNullException.ThrowIfNull(value);
this.Push(value.Low);
this.Push(value.High);
}
protected override void SetWord(Register16 value)
{
ArgumentNullException.ThrowIfNull(value);
//ArgumentNullException.ThrowIfNull(value);
this.MemoryWrite(value.High);
this.Bus.Address.Increment();
this.MemoryWrite(value.Low);
@@ -66,7 +66,7 @@ namespace EightBit
protected override void SetPaged(Register16 value)
{
ArgumentNullException.ThrowIfNull(value);
//ArgumentNullException.ThrowIfNull(value);
this.MemoryWrite(value.High);
++this.Bus.Address.Low;
this.MemoryWrite(value.Low);
+28
View File
@@ -4,58 +4,86 @@
namespace EightBit
{
using System.Runtime.CompilerServices;
public class Chip : Device
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static byte Bit(int which) => (byte)(1 << which);
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static byte Bit(byte which) => Bit((int)which);
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static byte SetBit(byte input, byte which) => (byte)(input | which);
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static byte SetBit(byte input, byte which, int condition) => SetBit(input, which, condition != 0);
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static byte SetBit(byte input, byte which, bool condition) => condition ? SetBit(input, which) : ClearBit(input, which);
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static byte ClearBit(byte input, byte which) => (byte)(input & (byte)~which);
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static byte ClearBit(byte input, byte which, int condition) => ClearBit(input, which, condition != 0);
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static byte ClearBit(byte input, byte which, bool condition) => SetBit(input, which, !condition);
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static byte HighByte(int value) => (byte)(value >> 8);
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static byte HighByte(ushort value) => HighByte((int)value);
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static byte LowByte(int value) => (byte)(value & (int)Mask.Eight);
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static byte LowByte(ushort value) => LowByte((int)value);
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static ushort PromoteByte(byte value) => (ushort)(value << 8);
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static byte DemoteByte(ushort value) => HighByte(value);
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static ushort HigherPart(ushort value) => (ushort)(value & 0xff00);
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static byte LowerPart(ushort value) => LowByte(value);
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static ushort MakeWord(byte low, byte high) => (ushort)(PromoteByte(high) | low);
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static int HighNibble(byte value) => value >> 4;
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static int LowNibble(byte value) => value & 0xf;
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static int HigherNibble(byte value) => value & 0xf0;
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static int LowerNibble(byte value) => LowNibble(value);
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static int PromoteNibble(byte value) => LowByte(value << 4);
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static int DemoteNibble(byte value) => HighNibble(value);
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static int CountBits(uint value) => System.Numerics.BitOperations.PopCount(value);
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static bool EvenParity(uint value) => CountBits(value) % 2 == 0;
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static int FindFirstSet(uint value) => value == 0 ? 0 : System.Numerics.BitOperations.TrailingZeroCount(value) + 1;
}
}
+3 -3
View File
@@ -88,13 +88,12 @@ namespace EightBit
protected abstract void EnableInterrupts();
protected override Register16 IncrementPC()
protected override void IncrementPC()
{
if (this.HALT.Raised())
{
base.IncrementPC();
}
return this.PC;
}
protected override byte FetchInstruction()
@@ -145,7 +144,8 @@ namespace EightBit
protected sealed override void Push(byte value)
{
this.MemoryWrite(this.SP.Decrement(), value);
this.SP.Decrement();
this.MemoryWrite(this.SP, value);
}
protected sealed override byte Pop()
+8 -8
View File
@@ -15,21 +15,21 @@ namespace EightBit
public override void PokeWord(ushort address, Register16 value)
{
ArgumentNullException.ThrowIfNull(value);
//ArgumentNullException.ThrowIfNull(value);
this.Bus.Poke(address, value.Low);
this.Bus.Poke(++address, value.High);
}
protected override void FetchInto(Register16 into)
{
ArgumentNullException.ThrowIfNull(into);
//ArgumentNullException.ThrowIfNull(into);
into.Low = this.FetchByte();
into.High = this.FetchByte();
}
protected override void GetInto(Register16 into)
{
ArgumentNullException.ThrowIfNull(into);
//ArgumentNullException.ThrowIfNull(into);
into.Low = this.MemoryRead();
this.Bus.Address.Increment();
into.High = this.MemoryRead();
@@ -37,7 +37,7 @@ namespace EightBit
protected override void GetPagedInto(Register16 into)
{
ArgumentNullException.ThrowIfNull(into);
//ArgumentNullException.ThrowIfNull(into);
into.Low = this.MemoryRead();
++this.Bus.Address.Low;
into.High = this.MemoryRead();
@@ -45,21 +45,21 @@ namespace EightBit
protected override void PopInto(Register16 into)
{
ArgumentNullException.ThrowIfNull(into);
//ArgumentNullException.ThrowIfNull(into);
into.Low = this.Pop();
into.High = this.Pop();
}
protected override void PushWord(Register16 value)
{
ArgumentNullException.ThrowIfNull(value);
//ArgumentNullException.ThrowIfNull(value);
this.Push(value.High);
this.Push(value.Low);
}
protected override void SetWord(Register16 value)
{
ArgumentNullException.ThrowIfNull(value);
//ArgumentNullException.ThrowIfNull(value);
this.MemoryWrite(value.Low);
this.Bus.Address.Increment();
this.MemoryWrite(value.High);
@@ -67,7 +67,7 @@ namespace EightBit
protected override void SetPaged(Register16 value)
{
ArgumentNullException.ThrowIfNull(value);
//ArgumentNullException.ThrowIfNull(value);
this.MemoryWrite(value.Low);
++this.Bus.Address.Low;
this.MemoryWrite(value.High);
+2 -2
View File
@@ -201,9 +201,9 @@ namespace EightBit
protected virtual byte BusRead() => this.Bus.Read(); // N.B. Should be the only real call into the "Bus.Read" code.
protected virtual Register16 IncrementPC() => this.PC.Increment();
protected virtual void IncrementPC() => this.PC.Increment();
protected virtual Register16 DecrementPC() => this.PC.Decrement();
protected virtual void DecrementPC() => this.PC.Decrement();
protected virtual void ImmediateAddress()
{
+11 -30
View File
@@ -4,13 +4,10 @@
namespace EightBit
{
using System.Runtime.InteropServices;
[StructLayout(LayoutKind.Explicit, Size = 2)]
public sealed class Register16
{
[FieldOffset(0)] private byte _low;
[FieldOffset(1)] private byte _high;
private byte _low;
private byte _high;
public Register16(byte low, byte high)
{
@@ -44,26 +41,18 @@ namespace EightBit
public Register16(Register16 rhs)
{
ArgumentNullException.ThrowIfNull(rhs);
//ArgumentNullException.ThrowIfNull(rhs);
this.Low = rhs.Low;
this.High = rhs.High;
}
public unsafe ushort Word
public ushort Word
{
get
{
fixed (byte* bytes = &this._low)
{
return *(ushort*)bytes;
}
}
get => Chip.MakeWord(this._low, this._high);
set
{
fixed (byte* bytes = &this._low)
{
*(ushort*)bytes = value;
}
this._low = Chip.LowByte(value);
this._high = Chip.HighByte(value);
}
}
@@ -73,7 +62,7 @@ namespace EightBit
public static bool operator ==(Register16 left, Register16 right)
{
ArgumentNullException.ThrowIfNull(left);
//ArgumentNullException.ThrowIfNull(left);
return left.Equals(right);
}
@@ -93,21 +82,13 @@ namespace EightBit
public void Assign(Register16 from)
{
ArgumentNullException.ThrowIfNull(from);
//ArgumentNullException.ThrowIfNull(from);
this.Low = from.Low;
this.High = from.High;
}
public Register16 Increment()
{
++this.Word;
return this;
}
public void Increment() => ++this.Word;
public Register16 Decrement()
{
--this.Word;
return this;
}
public void Decrement() => --this.Word;
}
}
+10 -5
View File
@@ -380,14 +380,19 @@ namespace Intel8080
break;
case 3: // 16-bit INC/DEC
_ = q switch
switch(q)
{
// INC rp
0 => this.RP(p).Increment(),
case 0:
this.RP(p).Increment();
break;
// DEC rp
1 => this.RP(p).Decrement(),
_ => throw new NotSupportedException("Invalid operation mode"),
};
case 1:
this.RP(p).Decrement();
break;
default:
throw new NotSupportedException("Invalid operation mode");
}
this.Tick();
break;
case 4: // 8-bit INC
+5 -1
View File
@@ -593,7 +593,11 @@ namespace MC6809
protected override void Push(byte value) => this.PushS(value);
private void Push(Register16 stack, byte value) => this.MemoryWrite(stack.Decrement(), value);
private void Push(Register16 stack, byte value)
{
stack.Decrement();
this.MemoryWrite(stack, value);
}
private void PushS(byte value) => this.Push(this.S, value);
+2 -1
View File
@@ -2004,7 +2004,8 @@ namespace Z80
private void RepeatBlockInstruction()
{
this.MEMPTR.Assign(this.DecrementPC());
this.DecrementPC();
this.MEMPTR.Assign(this.PC);
this.DecrementPC();
this.AdjustXY(this.PC.High);
}