From 0c8ed57b0de5d71c486686fd95ce7282f2d0464e Mon Sep 17 00:00:00 2001 From: Adrian Conlon <98398945+AdrianConlon@users.noreply.github.com> Date: Mon, 1 Jul 2024 23:27:35 +0100 Subject: [PATCH] Add easy to use Register16 assignment methods --- EightBit/Bus.cs | 6 +-- EightBit/IntelProcessor.cs | 18 +++---- EightBit/Processor.cs | 31 ++++------- EightBit/Register16.cs | 11 ++++ M6502/M6502.Test/Board.cs | 1 + M6502/M6502.cs | 3 +- M6502/M6502Core.cs | 31 +++++------ Z80/Z80.Test/Board.cs | 7 ++- Z80/Z80.cs | 102 +++++++++++++++++-------------------- 9 files changed, 98 insertions(+), 112 deletions(-) diff --git a/EightBit/Bus.cs b/EightBit/Bus.cs index 57508a8..15d8880 100644 --- a/EightBit/Bus.cs +++ b/EightBit/Bus.cs @@ -54,8 +54,7 @@ namespace EightBit public byte Read(byte low, byte high) { - this.Address.Low = low; - this.Address.High = high; + this.Address.Assign(low, high); return this.Read(); } @@ -83,8 +82,7 @@ namespace EightBit public void Write(byte low, byte high, byte value) { - this.Address.Low = low; - this.Address.High = high; + this.Address.Assign(low, high); this.Write(value); } diff --git a/EightBit/IntelProcessor.cs b/EightBit/IntelProcessor.cs index 311b836..64be277 100644 --- a/EightBit/IntelProcessor.cs +++ b/EightBit/IntelProcessor.cs @@ -143,24 +143,21 @@ namespace EightBit protected sealed override Register16 GetWord() { var returned = base.GetWord(); - this.MEMPTR.Low = this.Bus.Address.Low; - this.MEMPTR.High = this.Bus.Address.High; + this.MEMPTR.Assign(this.Bus.Address); return returned; } protected sealed override void SetWord(Register16 value) { base.SetWord(value); - this.MEMPTR.Low = this.Bus.Address.Low; - this.MEMPTR.High = this.Bus.Address.High; + this.MEMPTR.Assign(this.Bus.Address); } //// protected void Restart(byte address) { - this.MEMPTR.Low = address; - this.MEMPTR.High = 0; + this.MEMPTR.Assign(address, 0); this.Call(this.MEMPTR); } @@ -199,8 +196,7 @@ namespace EightBit protected void FetchWordMEMPTR() { this.FetchWord(); - this.MEMPTR.Low = this.Intermediate.Low; - this.MEMPTR.High = this.Intermediate.High; + this.MEMPTR.Assign(this.Intermediate); } protected void JumpIndirect() @@ -223,8 +219,7 @@ namespace EightBit protected bool JumpRelativeConditional(bool condition) { - this.Intermediate.Low = this.PC.Low; - this.Intermediate.High = this.PC.High; + this.Intermediate.Assign(this.PC); ++this.PC.Word; if (condition) { @@ -238,8 +233,7 @@ namespace EightBit protected override sealed void Return() { base.Return(); - this.MEMPTR.Low = this.PC.Low; - this.MEMPTR.High = this.PC.High; + this.MEMPTR.Assign(this.PC); } } } diff --git a/EightBit/Processor.cs b/EightBit/Processor.cs index 10ed0ef..0c77ca4 100644 --- a/EightBit/Processor.cs +++ b/EightBit/Processor.cs @@ -138,15 +138,13 @@ namespace EightBit protected void MemoryWrite(byte low, byte high) { - this.Bus.Address.Low = low; - this.Bus.Address.High = high; + this.Bus.Address.Assign(low, high); this.MemoryWrite(); } protected void MemoryWrite(byte low, byte high, byte data) { - this.Bus.Address.Low = low; - this.Bus.Address.High = high; + this.Bus.Address.Assign(low, high); this.MemoryWrite(data); } @@ -172,8 +170,7 @@ namespace EightBit protected byte MemoryRead(byte low, byte high) { - this.Bus.Address.Low = low; - this.Bus.Address.High = high; + this.Bus.Address.Assign(low, high); return this.MemoryRead(); } @@ -191,9 +188,9 @@ namespace EightBit protected byte FetchByte() { - var returned = this.MemoryRead(this.PC); + this.Bus.Address.Assign(this.PC); this.PC.Word++; - return returned; + return this.MemoryRead(); } protected abstract Register16 GetWord(); @@ -209,8 +206,7 @@ namespace EightBit protected Register16 GetWordPaged(byte page, byte offset) { - this.Bus.Address.Low = offset; - this.Bus.Address.High = page; + this.Bus.Address.Assign(offset, page); return this.GetWordPaged(); } @@ -223,8 +219,7 @@ namespace EightBit protected void SetWordPaged(byte page, byte offset, Register16 value) { - this.Bus.Address.Low = offset; - this.Bus.Address.High = page; + this.Bus.Address.Assign(offset, page); this.SetWordPaged(value); } @@ -233,8 +228,7 @@ namespace EightBit protected void FetchWordAddress() { this.FetchWord(); - this.Bus.Address.Low = this.Intermediate.Low; - this.Bus.Address.High = this.Intermediate.High; + this.Bus.Address.Assign(this.Intermediate); } protected abstract void Push(byte value); @@ -253,8 +247,7 @@ namespace EightBit protected Register16 GetWord(Register16 address) { - this.Bus.Address.Low = address.Low; - this.Bus.Address.High = address.High; + this.Bus.Address.Assign(address); return this.GetWord(); } @@ -266,8 +259,7 @@ namespace EightBit protected void SetWord(Register16 address, Register16 value) { - this.Bus.Address.Low = address.Low; - this.Bus.Address.High = address.High; + this.Bus.Address.Assign(address); this.SetWord(value); } @@ -275,8 +267,7 @@ namespace EightBit protected void Jump(Register16 destination) { - this.PC.Low = destination.Low; - this.PC.High = destination.High; + this.PC.Assign(destination); } protected void Call(ushort destination) diff --git a/EightBit/Register16.cs b/EightBit/Register16.cs index 16813b1..4f43143 100644 --- a/EightBit/Register16.cs +++ b/EightBit/Register16.cs @@ -90,5 +90,16 @@ namespace EightBit return rhs.Low == this.Low && rhs.High == this.High; } + + public void Assign(byte low, byte high) + { + this.low = low; + this.high = high; + } + + public void Assign(Register16 from) + { + this.Assign(from.low, from.high); + } } } diff --git a/M6502/M6502.Test/Board.cs b/M6502/M6502.Test/Board.cs index 131028d..024531c 100644 --- a/M6502/M6502.Test/Board.cs +++ b/M6502/M6502.Test/Board.cs @@ -203,6 +203,7 @@ namespace M6502.Test { var proportion = (double)e.Cycles / this.profiler.TotalCycleCount; Console.Out.Write(string.Format(CultureInfo.InvariantCulture, "\t[{0:P2}][{1:d9}][{2:d9}]\t{3}\n", proportion, e.Cycles, e.Count, e.Scope)); + Console.Out.Write(string.Format(CultureInfo.InvariantCulture, "\t[{0:P2}][{1:d9}][{2:d9}]\t{3}\n", proportion, cycles, count, name)); } private void Profiler_EmitLine(object? sender, ProfileLineEventArgs e) diff --git a/M6502/M6502.cs b/M6502/M6502.cs index 31dc912..c26e0f1 100644 --- a/M6502/M6502.cs +++ b/M6502/M6502.cs @@ -219,8 +219,7 @@ namespace EightBit private void Jam() { - this.Bus.Address.Low = this.PC.Low; - this.Bus.Address.High = this.PC.High; + this.Bus.Address.Assign(this.PC); --this.PC.Word; this.MemoryRead(); this.MemoryRead(); diff --git a/M6502/M6502Core.cs b/M6502/M6502Core.cs index b3dee76..6747f0b 100644 --- a/M6502/M6502Core.cs +++ b/M6502/M6502Core.cs @@ -640,8 +640,7 @@ namespace EightBit private void UpdateStack(byte position) { - this.Bus.Address.Low = position; - this.Bus.Address.High = 1; + this.Bus.Address.Assign(position, 1); } private void LowerStack() => this.UpdateStack(this.S--); @@ -718,10 +717,15 @@ namespace EightBit this.Bus.Address.Low = this.Intermediate.Low; } + private void GetAddressPaged() + { + this.GetWordPaged(); + this.Bus.Address.Assign(this.Intermediate); + } + protected void ImmediateAddress() { - this.Bus.Address.Low = this.PC.Low; - this.Bus.Address.High = this.PC.High; + this.Bus.Address.Assign(this.PC); ++this.PC.Word; } @@ -729,24 +733,19 @@ namespace EightBit protected void ZeroPageAddress() { - this.Bus.Address.Low = this.FetchByte(); - this.Bus.Address.High = 0; + this.Bus.Address.Assign(this.FetchByte(), 0); } protected void ZeroPageIndirectAddress() { this.ZeroPageAddress(); - this.GetWordPaged(); - this.Bus.Address.Low = this.Intermediate.Low; - this.Bus.Address.High = this.Intermediate.High; + this.GetAddressPaged(); } protected void IndirectAddress() { this.AbsoluteAddress(); - this.GetWordPaged(); - this.Bus.Address.Low = this.Intermediate.Low; - this.Bus.Address.High = this.Intermediate.High; + this.GetAddressPaged(); } protected void ZeroPageWithIndexAddress(byte index) @@ -772,9 +771,7 @@ namespace EightBit protected void IndexedIndirectXAddress() { this.ZeroPageXAddress(); - this.GetWordPaged(); - this.Bus.Address.Low = this.Intermediate.Low; - this.Bus.Address.High = this.Intermediate.High; + this.GetAddressPaged(); } protected void IndirectIndexedYAddress() @@ -1054,8 +1051,8 @@ namespace EightBit this.Intermediate.Low = this.FetchByte(); this.SwallowPop(); this.PushWord(this.PC); - this.PC.High = this.FetchByte(); - this.PC.Low = this.Intermediate.Low; + this.Intermediate.High = this.FetchByte(); + this.PC.Assign(this.Intermediate); } private void PHP() => this.Push(SetBit(this.P, StatusBits.BF)); diff --git a/Z80/Z80.Test/Board.cs b/Z80/Z80.Test/Board.cs index a808795..aea87ee 100644 --- a/Z80/Z80.Test/Board.cs +++ b/Z80/Z80.Test/Board.cs @@ -83,7 +83,12 @@ namespace Z80.Test private void CPU_ExecutingInstruction_CPM(object sender, System.EventArgs e) { - switch (this.CPU.PC.Word) + if (this.CPU.PC.High != 0) + { + // We're only interested in zero page + return; + } + switch (this.CPU.PC.Low) { case 0x0: // CP/M warm start if (++this.warmstartCount == 2) diff --git a/Z80/Z80.cs b/Z80/Z80.cs index 418c96c..6ef88fc 100644 --- a/Z80/Z80.cs +++ b/Z80/Z80.cs @@ -538,8 +538,7 @@ namespace EightBit break; case 2: this.Tick(7); - this.MEMPTR.Low = data; - this.MEMPTR.High = this.IV; + this.MEMPTR.Assign(data, this.IV); this.Call(this.MEMPTR); break; default: @@ -804,8 +803,8 @@ namespace EightBit switch (z) { case 0: // Input from port with 16-bit address - this.MEMPTR.Low = this.Bus.Address.Low = this.BC.Low; - this.MEMPTR.High = this.Bus.Address.High = this.BC.High; + this.Bus.Address.Assign(this.BC); + this.MEMPTR.Assign(Bus.Address); this.MEMPTR.Word++; this.ReadPort(); if (y != 6) @@ -817,19 +816,19 @@ namespace EightBit this.F = ClearBit(this.F, StatusBits.NF | StatusBits.HC); break; case 1: // Output to port with 16-bit address - this.MEMPTR.Low = this.Bus.Address.Low = this.BC.Low; - this.MEMPTR.High = this.Bus.Address.High = this.BC.High; + this.Bus.Address.Assign(this.BC); + this.MEMPTR.Assign(Bus.Address); this.MEMPTR.Word++; this.Bus.Data = y != 6 ? this.R(y) : (byte)0; this.WritePort(); break; case 2: // 16-bit add/subtract with carry - this.HL2().Word = q switch + this.HL2().Assign(q switch { 0 => this.SBC(this.HL2(), this.RP(p)), // SBC HL, rp[p] 1 => this.ADC(this.HL2(), this.RP(p)), // ADC HL, rp[p] _ => throw new NotSupportedException("Invalid operation mode"), - }; + }); break; case 3: // Retrieve/store register pair from/to immediate address this.FetchWordAddress(); @@ -839,7 +838,7 @@ namespace EightBit this.SetWord(this.RP(p)); break; case 1: // LD rp[p], (nn) - this.RP(p).Word = this.GetWord().Word; + this.RP(p).Assign(this.GetWord()); break; default: throw new NotSupportedException("Invalid operation mode"); @@ -924,8 +923,7 @@ namespace EightBit if (this.LDIR()) { --this.PC.Word; - this.MEMPTR.Low = this.PC.Low; - this.MEMPTR.High = this.PC.High; + this.MEMPTR.Assign(this.PC); --this.PC.Word; } @@ -935,8 +933,7 @@ namespace EightBit if (this.LDDR()) { --this.PC.Word; - this.MEMPTR.Low = this.PC.Low; - this.MEMPTR.High = this.PC.High; + this.MEMPTR.Assign(this.PC); --this.PC.Word; } @@ -958,8 +955,7 @@ namespace EightBit if (this.CPIR()) { --this.PC.Word; - this.MEMPTR.Low = this.PC.Low; - this.MEMPTR.High = this.PC.High; + this.MEMPTR.Assign(this.PC); --this.PC.Word; this.Tick(5); } @@ -970,8 +966,7 @@ namespace EightBit if (this.CPDR()) { --this.PC.Word; - this.MEMPTR.Low = this.PC.Low; - this.MEMPTR.High = this.PC.High; + this.MEMPTR.Assign(this.PC); --this.PC.Word; this.Tick(3); } @@ -1093,10 +1088,10 @@ namespace EightBit switch (q) { case 0: // LD rp,nn - this.RP(p).Word = this.FetchWord().Word; + this.RP(p).Assign(this.FetchWord()); break; case 1: // ADD HL,rp - this.HL2().Word = this.Add(this.HL2(), this.RP(p)); + this.HL2().Assign(this.Add(this.HL2(), this.RP(p))); break; default: throw new NotSupportedException("Invalid operation mode"); @@ -1110,15 +1105,15 @@ namespace EightBit switch (p) { case 0: // LD (BC),A - this.MEMPTR.Low = this.Bus.Address.Low = this.BC.Low; - this.MEMPTR.High = this.Bus.Address.High = this.BC.High; + this.Bus.Address.Assign(this.BC); + this.MEMPTR.Assign(Bus.Address); ++this.MEMPTR.Word; this.MEMPTR.High = this.Bus.Data = this.A; this.MemoryWrite(); break; case 1: // LD (DE),A - this.MEMPTR.Low = this.Bus.Address.Low = this.DE.Low; - this.MEMPTR.High = this.Bus.Address.High = this.DE.High; + this.Bus.Address.Assign(this.DE); + this.MEMPTR.Assign(Bus.Address); ++this.MEMPTR.Word; this.MEMPTR.High = this.Bus.Data = this.A; this.MemoryWrite(); @@ -1129,8 +1124,7 @@ namespace EightBit break; case 3: // LD (nn),A this.FetchWordMEMPTR(); - this.Bus.Address.Low = this.MEMPTR.Low; - this.Bus.Address.High = this.MEMPTR.High; + this.Bus.Address.Assign(this.MEMPTR); ++this.MEMPTR.Word; this.MEMPTR.High = this.Bus.Data = this.A; this.MemoryWrite(); @@ -1144,25 +1138,24 @@ namespace EightBit switch (p) { case 0: // LD A,(BC) - this.MEMPTR.Low = this.Bus.Address.Low = this.BC.Low; - this.MEMPTR.High = this.Bus.Address.High = this.BC.High; + this.Bus.Address.Assign(this.BC); + this.MEMPTR.Assign(Bus.Address); ++this.MEMPTR.Word; this.A = this.MemoryRead(); break; case 1: // LD A,(DE) - this.MEMPTR.Low = this.Bus.Address.Low = this.DE.Low; - this.MEMPTR.High = this.Bus.Address.High = this.DE.High; + this.Bus.Address.Assign(this.DE); + this.MEMPTR.Assign(Bus.Address); ++this.MEMPTR.Word; this.A = this.MemoryRead(); break; case 2: // LD HL,(nn) this.FetchWordAddress(); - this.HL2().Word = this.GetWord().Word; + this.HL2().Assign(this.GetWord()); break; case 3: // LD A,(nn) this.FetchWordMEMPTR(); - this.Bus.Address.Low = this.MEMPTR.Low; - this.Bus.Address.High = this.MEMPTR.High; + this.Bus.Address.Assign(this.MEMPTR); ++this.MEMPTR.Word; this.A = this.MemoryRead(); break; @@ -1402,7 +1395,7 @@ namespace EightBit switch (q) { case 0: // POP rp2[p] - this.RP2(p).Word = this.PopWord().Word; + this.RP2(p).Assign(this.PopWord()); break; case 1: switch (p) @@ -1417,7 +1410,7 @@ namespace EightBit this.Jump(this.HL2()); break; case 3: // LD SP,HL - this.SP.Word = this.HL2().Word; + this.SP.Assign(this.HL2()); break; default: throw new NotSupportedException("Invalid operation mode"); @@ -1598,8 +1591,7 @@ namespace EightBit this.LowerM1(); var returned = this.MemoryRead(this.PC); this.RaiseM1(); - this.Bus.Address.Low = this.REFRESH; - this.Bus.Address.High = this.IV; + this.Bus.Address.Assign(this.REFRESH, this.IV); this.LowerRFSH(); this.LowerMREQ(); this.RaiseMREQ(); @@ -1678,7 +1670,7 @@ namespace EightBit private void CallConditionalFlag(int flag) => this.CallConditional(this.ConvertCondition(flag)); - private ushort SBC(Register16 operand, Register16 value) + private Register16 SBC(Register16 operand, Register16 value) { var subtraction = operand.Word - value.Word - (this.F & (byte)StatusBits.CF); this.Intermediate.Word = (ushort)subtraction; @@ -1698,10 +1690,10 @@ namespace EightBit this.MEMPTR.Word = (ushort)(operand.Word + 1); - return this.Intermediate.Word; + return this.Intermediate; } - private ushort ADC(Register16 operand, Register16 value) + private Register16 ADC(Register16 operand, Register16 value) { this.Add(operand, value, this.F & (byte)StatusBits.CF); // Leaves result in intermediate anyway this.F = ClearBit(this.F, StatusBits.ZF, this.Intermediate.Word); @@ -1713,10 +1705,10 @@ namespace EightBit this.F = SetBit(this.F, StatusBits.SF, afterNegative); this.F = AdjustOverflowAdd(this.F, beforeNegative, valueNegative, afterNegative); - return this.Intermediate.Word; + return this.Intermediate; } - private ushort Add(Register16 operand, Register16 value, int carry = 0) + private Register16 Add(Register16 operand, Register16 value, int carry = 0) { var addition = operand.Word + value.Word + carry; this.Intermediate.Word = (ushort)addition; @@ -1728,7 +1720,7 @@ namespace EightBit this.MEMPTR.Word = (ushort)(operand.Word + 1); - return this.Intermediate.Word; + return this.Intermediate; } private byte Add(byte operand, byte value, int carry = 0) @@ -2022,8 +2014,8 @@ namespace EightBit private void BlockIn(Register16 source, Register16 destination) { - this.MEMPTR.Low = this.Bus.Address.Low = source.Low; - this.MEMPTR.High = this.Bus.Address.High = source.High; + this.Bus.Address.Assign(source); + this.MEMPTR.Assign(Bus.Address); this.Tick(); this.ReadPort(); this.Tick(3); @@ -2063,11 +2055,9 @@ namespace EightBit this.Tick(); this.MemoryRead(source); destination.High = this.Decrement(destination.High); - this.Bus.Address.Low = destination.Low; - this.Bus.Address.High = destination.High; + this.Bus.Address.Assign(destination); this.WritePort(); - this.MEMPTR.Low = destination.Low; - this.MEMPTR.High = destination.High; + this.MEMPTR.Assign(destination); } private void AdjustBlockOutFlags() @@ -2125,8 +2115,8 @@ namespace EightBit private void RRD() { - this.MEMPTR.Low = this.Bus.Address.Low = this.HL.Low; - this.MEMPTR.High = this.Bus.Address.High = this.HL.High; + this.Bus.Address.Assign(this.HL); + this.MEMPTR.Assign(this.Bus.Address); ++this.MEMPTR.Word; var memory = this.MemoryRead(); this.Tick(4); @@ -2138,8 +2128,8 @@ namespace EightBit private void RLD() { - this.MEMPTR.Low = this.Bus.Address.Low = this.HL.Low; - this.MEMPTR.High = this.Bus.Address.High = this.HL.High; + this.Bus.Address.Assign(this.HL); + this.MEMPTR.Assign(this.Bus.Address); ++this.MEMPTR.Word; var memory = this.MemoryRead(); this.Tick(4); @@ -2151,8 +2141,8 @@ namespace EightBit private void WritePort(byte port) { - this.MEMPTR.Low = this.Bus.Address.Low = port; - this.MEMPTR.High = this.Bus.Address.High = this.Bus.Data = this.A; + this.Bus.Address.Assign(port, this.Bus.Data = this.A); + this.MEMPTR.Assign(this.Bus.Address); this.WritePort(); ++this.MEMPTR.Low; } @@ -2169,8 +2159,8 @@ namespace EightBit private byte ReadPort(byte port) { - this.MEMPTR.Low = this.Bus.Address.Low = port; - this.MEMPTR.High = this.Bus.Address.High = this.A; + this.Bus.Address.Assign(port, this.Bus.Data = this.A); + this.MEMPTR.Assign(this.Bus.Address); ++this.MEMPTR.Low; return this.ReadPort(); }