From 56f46a8236232834054374bacb874512a1fff1a9 Mon Sep 17 00:00:00 2001 From: Adrian Conlon Date: Thu, 7 Mar 2019 00:28:39 +0000 Subject: [PATCH 1/3] Speed up Z80 block operations by using values rather than reference objects, if possible. Signed-off-by: Adrian Conlon --- Z80/Z80.cs | 24 ++++++------------------ 1 file changed, 6 insertions(+), 18 deletions(-) diff --git a/Z80/Z80.cs b/Z80/Z80.cs index 6631522..f18ecb0 100644 --- a/Z80/Z80.cs +++ b/Z80/Z80.cs @@ -1800,7 +1800,7 @@ namespace EightBit hl2.High = this.MEMPTR.High; } - private void BlockCompare(Register16 source, Register16 counter) + private void BlockCompare(ushort source, Register16 counter) { var value = this.BusRead(source); var result = (byte)(this.A - value); @@ -1819,8 +1819,7 @@ namespace EightBit private void CPI() { - this.BlockCompare(this.HL, this.BC); - ++this.HL.Word; + this.BlockCompare(this.HL.Word++, this.BC); ++this.MEMPTR.Word; } @@ -1832,8 +1831,7 @@ namespace EightBit private void CPD() { - this.BlockCompare(this.HL, this.BC); - --this.HL.Word; + this.BlockCompare(this.HL.Word--, this.BC); --this.MEMPTR.Word; } @@ -1843,7 +1841,7 @@ namespace EightBit return ((this.F & (byte)StatusBits.PF) != 0) && ((this.F & (byte)StatusBits.ZF) == 0); // See CPD } - private void BlockLoad(Register16 source, Register16 destination, Register16 counter) + private void BlockLoad(ushort source, ushort destination, Register16 counter) { var value = this.BusRead(source); this.BusWrite(destination, value); @@ -1854,12 +1852,7 @@ namespace EightBit this.F = SetFlag(this.F, StatusBits.PF, --counter.Word); } - private void LDI() - { - this.BlockLoad(this.HL, this.DE, this.BC); - ++this.HL.Word; - ++this.DE.Word; - } + private void LDI() => this.BlockLoad(this.HL.Word++, this.DE.Word++, this.BC); private bool LDIR() { @@ -1867,12 +1860,7 @@ namespace EightBit return (this.F & (byte)StatusBits.PF) != 0; // See LDI } - private void LDD() - { - this.BlockLoad(this.HL, this.DE, this.BC); - --this.HL.Word; - --this.DE.Word; - } + private void LDD() => this.BlockLoad(this.HL.Word--, this.DE.Word--, this.BC); private bool LDDR() { From e80963260d98780e3989d1359fd828e9711d39a0 Mon Sep 17 00:00:00 2001 From: Adrian Conlon Date: Thu, 7 Mar 2019 01:21:00 +0000 Subject: [PATCH 2/3] Try to avoid copying around Register16 references, if possible. Signed-off-by: Adrian Conlon --- EightBit/IntelProcessor.cs | 8 ++++---- EightBit/Processor.cs | 4 ---- Intel8080/Intel8080.cs | 6 +++--- M6502/M6502.cs | 6 +++--- Z80/Z80.cs | 34 +++++++++++++++------------------- 5 files changed, 25 insertions(+), 33 deletions(-) diff --git a/EightBit/IntelProcessor.cs b/EightBit/IntelProcessor.cs index 7f70d88..c2199ab 100644 --- a/EightBit/IntelProcessor.cs +++ b/EightBit/IntelProcessor.cs @@ -138,7 +138,7 @@ namespace EightBit { this.MEMPTR.Low = address; this.MEMPTR.High = 0; - this.Call(this.MEMPTR); + this.Call(this.MEMPTR.Word); } protected bool CallConditional(bool condition) @@ -146,7 +146,7 @@ namespace EightBit this.MEMPTR.Word = this.FetchWord().Word; if (condition) { - this.Call(this.MEMPTR); + this.Call(this.MEMPTR.Word); } return condition; @@ -157,7 +157,7 @@ namespace EightBit this.MEMPTR.Word = this.FetchWord().Word; if (condition) { - this.Jump(this.MEMPTR); + this.Jump(this.MEMPTR.Word); } return condition; @@ -176,7 +176,7 @@ namespace EightBit protected void JumpRelative(sbyte offset) { this.MEMPTR.Word = (ushort)(this.PC.Word + offset); - this.Jump(this.MEMPTR); + this.Jump(this.MEMPTR.Word); } protected bool JumpRelativeConditional(bool condition) diff --git a/EightBit/Processor.cs b/EightBit/Processor.cs index 055e017..a9fa486 100644 --- a/EightBit/Processor.cs +++ b/EightBit/Processor.cs @@ -186,16 +186,12 @@ namespace EightBit protected void Jump(ushort destination) => this.PC.Word = destination; - protected void Jump(Register16 destination) => this.Jump(destination.Word); - protected void Call(ushort destination) { this.PushWord(this.PC); this.Jump(destination); } - protected void Call(Register16 destination) => this.Call(destination.Word); - protected virtual void Return() => this.Jump(this.PopWord().Word); } } diff --git a/Intel8080/Intel8080.cs b/Intel8080/Intel8080.cs index 294d1d1..ae4a04b 100644 --- a/Intel8080/Intel8080.cs +++ b/Intel8080/Intel8080.cs @@ -479,7 +479,7 @@ namespace EightBit this.Tick(10); break; case 2: // JP HL - this.Jump(this.HL); + this.Jump(this.HL.Word); this.Tick(4); break; case 3: // LD SP,HL @@ -502,7 +502,7 @@ namespace EightBit switch (y) { case 0: // JP nn - this.Jump(this.FetchWord()); + this.Jump(this.FetchWord().Word); this.Tick(10); break; case 2: // OUT (n),A @@ -551,7 +551,7 @@ namespace EightBit switch (p) { case 0: // CALL nn - this.Call(this.FetchWord()); + this.Call(this.FetchWord().Word); this.Tick(17); break; } diff --git a/M6502/M6502.cs b/M6502/M6502.cs index e754071..ccb713d 100644 --- a/M6502/M6502.cs +++ b/M6502/M6502.cs @@ -233,7 +233,7 @@ namespace EightBit case 0x49: this.A = this.EorR(this.A, this.AM_Immediate()); break; // EOR (immediate) case 0x4a: this.BusRead(); this.A = this.LSR(this.A); break; // LSR A (implied) case 0x4b: this.ASR(this.AM_Immediate()); break; // *ASR (immediate) - case 0x4c: this.Jump(this.Address_Absolute()); break; // JMP (absolute) + case 0x4c: this.Jump(this.Address_Absolute().Word); break; // JMP (absolute) case 0x4d: this.A = this.EorR(this.A, this.AM_Absolute()); break; // EOR (absolute) case 0x4e: this.BusReadModifyWrite(this.LSR(this.AM_Absolute())); break; // LSR (absolute) case 0x4f: this.SRE(this.AM_Absolute()); break; // *SRE (absolute) @@ -267,7 +267,7 @@ namespace EightBit case 0x69: this.A = this.ADC(this.A, this.AM_Immediate()); break; // ADC (immediate) case 0x6a: this.BusRead(); this.A = this.ROR(this.A); break; // ROR A (implied) case 0x6b: this.ARR(this.AM_Immediate()); break; // *ARR (immediate) - case 0x6c: this.Jump(this.Address_Indirect()); break; // JMP (indirect) + case 0x6c: this.Jump(this.Address_Indirect().Word); break; // JMP (indirect) case 0x6d: this.A = this.ADC(this.A, this.AM_Absolute()); break; // ADC (absolute) case 0x6e: this.BusReadModifyWrite(this.ROR(this.AM_Absolute())); break; // ROR (absolute) case 0x6f: this.RRA(this.AM_Absolute()); break; // *RRA (absolute) @@ -589,7 +589,7 @@ namespace EightBit this.P = SetFlag(this.P, StatusBits.IF); // Disable IRQ var vector = reset ? RSTvector : (nmi ? NMIvector : IRQvector); - this.Jump(this.GetWordPaged(0xff, vector)); + this.Jump(this.GetWordPaged(0xff, vector).Word); this.handlingRESET = this.handlingNMI = this.handlingINT = false; } diff --git a/Z80/Z80.cs b/Z80/Z80.cs index f18ecb0..2005986 100644 --- a/Z80/Z80.cs +++ b/Z80/Z80.cs @@ -1222,7 +1222,7 @@ namespace EightBit this.Tick(4); break; case 2: // JP HL - this.Jump(this.HL2()); + this.Jump(this.HL2().Word); this.Tick(4); break; case 3: // LD SP,HL @@ -1800,12 +1800,12 @@ namespace EightBit hl2.High = this.MEMPTR.High; } - private void BlockCompare(ushort source, Register16 counter) + private void BlockCompare(ushort source, ushort counter) { var value = this.BusRead(source); var result = (byte)(this.A - value); - this.F = SetFlag(this.F, StatusBits.PF, --counter.Word); + this.F = SetFlag(this.F, StatusBits.PF, counter); this.F = AdjustSZ(this.F, result); this.F = AdjustHalfCarrySub(this.F, this.A, value, result); @@ -1819,7 +1819,7 @@ namespace EightBit private void CPI() { - this.BlockCompare(this.HL.Word++, this.BC); + this.BlockCompare(this.HL.Word++, --this.BC.Word); ++this.MEMPTR.Word; } @@ -1831,7 +1831,7 @@ namespace EightBit private void CPD() { - this.BlockCompare(this.HL.Word--, this.BC); + this.BlockCompare(this.HL.Word--, --this.BC.Word); --this.MEMPTR.Word; } @@ -1841,7 +1841,7 @@ namespace EightBit return ((this.F & (byte)StatusBits.PF) != 0) && ((this.F & (byte)StatusBits.ZF) == 0); // See CPD } - private void BlockLoad(ushort source, ushort destination, Register16 counter) + private void BlockLoad(ushort source, ushort destination, ushort counter) { var value = this.BusRead(source); this.BusWrite(destination, value); @@ -1849,10 +1849,10 @@ namespace EightBit this.F = SetFlag(this.F, StatusBits.XF, xy & (int)Bits.Bit3); this.F = SetFlag(this.F, StatusBits.YF, xy & (int)Bits.Bit1); this.F = ClearFlag(this.F, StatusBits.NF | StatusBits.HC); - this.F = SetFlag(this.F, StatusBits.PF, --counter.Word); + this.F = SetFlag(this.F, StatusBits.PF, counter); } - private void LDI() => this.BlockLoad(this.HL.Word++, this.DE.Word++, this.BC); + private void LDI() => this.BlockLoad(this.HL.Word++, this.DE.Word++, --this.BC.Word); private bool LDIR() { @@ -1860,7 +1860,7 @@ namespace EightBit return (this.F & (byte)StatusBits.PF) != 0; // See LDI } - private void LDD() => this.BlockLoad(this.HL.Word--, this.DE.Word--, this.BC); + private void LDD() => this.BlockLoad(this.HL.Word--, this.DE.Word--, --this.BC.Word); private bool LDDR() { @@ -1868,7 +1868,7 @@ namespace EightBit return (this.F & (byte)StatusBits.PF) != 0; // See LDD } - private void BlockIn(Register16 source, Register16 destination) + private void BlockIn(Register16 source, ushort destination) { this.MEMPTR.Word = this.Bus.Address.Word = source.Word; var value = this.ReadPort(); @@ -1879,8 +1879,7 @@ namespace EightBit private void INI() { - this.BlockIn(this.BC, this.HL); - ++this.HL.Word; + this.BlockIn(this.BC, this.HL.Word++); ++this.MEMPTR.Word; } @@ -1892,8 +1891,7 @@ namespace EightBit private void IND() { - this.BlockIn(this.BC, this.HL); - --this.HL.Word; + this.BlockIn(this.BC, this.HL.Word--); --this.MEMPTR.Word; } @@ -1903,7 +1901,7 @@ namespace EightBit return (this.F & (byte)StatusBits.ZF) == 0; // See IND } - private void BlockOut(Register16 source, Register16 destination) + private void BlockOut(ushort source, Register16 destination) { var value = this.BusRead(source); this.Bus.Address.Word = destination.Word; @@ -1917,8 +1915,7 @@ namespace EightBit private void OUTI() { - this.BlockOut(this.HL, this.BC); - ++this.HL.Word; + this.BlockOut(this.HL.Word++, this.BC); ++this.MEMPTR.Word; } @@ -1930,8 +1927,7 @@ namespace EightBit private void OUTD() { - this.BlockOut(this.HL, this.BC); - --this.HL.Word; + this.BlockOut(this.HL.Word--, this.BC); --this.MEMPTR.Word; } From 5b9a92c76c402d9d13305fe4f78a146396a45c67 Mon Sep 17 00:00:00 2001 From: Adrian Conlon Date: Thu, 7 Mar 2019 01:21:23 +0000 Subject: [PATCH 3/3] Correct a couple of small style issues. Signed-off-by: Adrian Conlon --- Intel8080/Intel8080.Test/Properties/AssemblyInfo.cs | 7 +++++-- Z80/Z80.Test/Board.cs | 6 +++--- Z80/Z80.Test/Properties/AssemblyInfo.cs | 7 +++++-- 3 files changed, 13 insertions(+), 7 deletions(-) diff --git a/Intel8080/Intel8080.Test/Properties/AssemblyInfo.cs b/Intel8080/Intel8080.Test/Properties/AssemblyInfo.cs index e1f8345..3537b11 100644 --- a/Intel8080/Intel8080.Test/Properties/AssemblyInfo.cs +++ b/Intel8080/Intel8080.Test/Properties/AssemblyInfo.cs @@ -1,5 +1,8 @@ -using System.Reflection; -using System.Runtime.CompilerServices; +// +// Copyright (c) Adrian Conlon. All rights reserved. +// + +using System.Reflection; using System.Runtime.InteropServices; // General Information about an assembly is controlled through the following diff --git a/Z80/Z80.Test/Board.cs b/Z80/Z80.Test/Board.cs index d0ab0e1..f9426a5 100644 --- a/Z80/Z80.Test/Board.cs +++ b/Z80/Z80.Test/Board.cs @@ -59,7 +59,7 @@ namespace Z80.Test this.Poke(0, 0xc3); // JMP this.CPU.PokeWord(1, this.configuration.StartAddress); - this.Poke(5, 0xc9); // ret + this.Poke(5, 0xc9); // ret } public override MemoryMapping Mapping(ushort absolute) => this.mapping; @@ -85,14 +85,14 @@ namespace Z80.Test { switch (this.CPU.PC.Word) { - case 0x0: // CP/M warm start + case 0x0: // CP/M warm start if (++this.warmstartCount == 2) { this.LowerPOWER(); } break; - case 0x5: // BDOS + case 0x5: // BDOS this.BDOS(); break; default: diff --git a/Z80/Z80.Test/Properties/AssemblyInfo.cs b/Z80/Z80.Test/Properties/AssemblyInfo.cs index cf8cfb2..8b09536 100644 --- a/Z80/Z80.Test/Properties/AssemblyInfo.cs +++ b/Z80/Z80.Test/Properties/AssemblyInfo.cs @@ -1,5 +1,8 @@ -using System.Reflection; -using System.Runtime.CompilerServices; +// +// Copyright (c) Adrian Conlon. All rights reserved. +// + +using System.Reflection; using System.Runtime.InteropServices; // General Information about an assembly is controlled through the following