diff --git a/EightBit/Bus.cs b/EightBit/Bus.cs index fcb588b..57508a8 100644 --- a/EightBit/Bus.cs +++ b/EightBit/Bus.cs @@ -50,7 +50,7 @@ namespace EightBit return this.Read(); } - public byte Read(Register16 absolute) => this.Read(absolute.Word); + public byte Read(Register16 absolute) => this.Read(absolute.Low, absolute.High); public byte Read(byte low, byte high) { @@ -79,7 +79,7 @@ namespace EightBit this.Write(value); } - public void Write(Register16 absolute, byte value) => this.Write(absolute.Word, value); + public void Write(Register16 absolute, byte value) => this.Write(absolute.Low, absolute.High, value); public void Write(byte low, byte high, byte value) { diff --git a/EightBit/IntelProcessor.cs b/EightBit/IntelProcessor.cs index f5455ca..311b836 100644 --- a/EightBit/IntelProcessor.cs +++ b/EightBit/IntelProcessor.cs @@ -127,21 +127,32 @@ namespace EightBit this.Jump(0); } - protected sealed override void Push(byte value) => this.MemoryWrite(--this.SP.Word, value); + protected sealed override void Push(byte value) + { + --this.SP.Word; + this.MemoryWrite(this.SP, value); + } - protected sealed override byte Pop() => this.MemoryRead(this.SP.Word++); + protected sealed override byte Pop() + { + var returned = this.MemoryRead(this.SP); + this.SP.Word++; + return returned; + } protected sealed override Register16 GetWord() { var returned = base.GetWord(); - this.MEMPTR.Word = this.Bus.Address.Word; + this.MEMPTR.Low = this.Bus.Address.Low; + this.MEMPTR.High = this.Bus.Address.High; return returned; } protected sealed override void SetWord(Register16 value) { base.SetWord(value); - this.MEMPTR.Word = this.Bus.Address.Word; + this.MEMPTR.Low = this.Bus.Address.Low; + this.MEMPTR.High = this.Bus.Address.High; } //// @@ -150,15 +161,15 @@ namespace EightBit { this.MEMPTR.Low = address; this.MEMPTR.High = 0; - this.Call(this.MEMPTR.Word); + this.Call(this.MEMPTR); } protected bool CallConditional(bool condition) { - this.MEMPTR.Word = this.FetchWord().Word; + this.FetchWordMEMPTR(); if (condition) { - this.Call(this.MEMPTR.Word); + this.Call(this.MEMPTR); } return condition; @@ -166,10 +177,10 @@ namespace EightBit protected bool JumpConditional(bool condition) { - this.MEMPTR.Word = this.FetchWord().Word; + this.FetchWordMEMPTR(); if (condition) { - this.Jump(this.MEMPTR.Word); + this.Jump(this.MEMPTR); } return condition; @@ -185,18 +196,39 @@ namespace EightBit return condition; } + protected void FetchWordMEMPTR() + { + this.FetchWord(); + this.MEMPTR.Low = this.Intermediate.Low; + this.MEMPTR.High = this.Intermediate.High; + } + + protected void JumpIndirect() + { + this.FetchWordMEMPTR(); + this.Jump(this.MEMPTR); + } + + protected void CallIndirect() + { + this.FetchWordMEMPTR(); + this.Call(this.MEMPTR); + } + protected void JumpRelative(sbyte offset) { this.MEMPTR.Word = (ushort)(this.PC.Word + offset); - this.Jump(this.MEMPTR.Word); + this.Jump(this.MEMPTR); } protected bool JumpRelativeConditional(bool condition) { - var offsetAddress = this.PC.Word++; + this.Intermediate.Low = this.PC.Low; + this.Intermediate.High = this.PC.High; + ++this.PC.Word; if (condition) { - var offset = (sbyte)this.MemoryRead(offsetAddress); + var offset = (sbyte)this.MemoryRead(this.Intermediate); this.JumpRelative(offset); } @@ -206,7 +238,8 @@ namespace EightBit protected override sealed void Return() { base.Return(); - this.MEMPTR.Word = this.PC.Word; + this.MEMPTR.Low = this.PC.Low; + this.MEMPTR.High = this.PC.High; } } } diff --git a/EightBit/Processor.cs b/EightBit/Processor.cs index 707e230..13d6a37 100644 --- a/EightBit/Processor.cs +++ b/EightBit/Processor.cs @@ -149,7 +149,7 @@ namespace EightBit this.MemoryWrite(data); } - protected void MemoryWrite(Register16 address, byte data) => this.MemoryWrite(address.Word, data); + protected void MemoryWrite(Register16 address, byte data) => this.MemoryWrite(address.Low, address.High, data); protected void MemoryWrite(byte data) { @@ -174,13 +174,18 @@ namespace EightBit return this.MemoryRead(); } - protected byte MemoryRead(Register16 address) => this.MemoryRead(address.Word); + protected byte MemoryRead(Register16 address) => this.MemoryRead(address.Low, address.High); protected virtual byte MemoryRead() => this.BusRead(); protected virtual byte BusRead() => this.Bus.Read(); // N.B. Should be the only real call into the "Bus.Read" code. - protected byte FetchByte() => this.MemoryRead(this.PC.Word++); + protected byte FetchByte() + { + var returned = this.MemoryRead(this.PC); + this.PC.Word++; + return returned; + } protected abstract Register16 GetWord(); @@ -216,6 +221,13 @@ namespace EightBit protected abstract Register16 FetchWord(); + protected void FetchWordAddress() + { + this.FetchWord(); + this.Bus.Address.Low = this.Intermediate.Low; + this.Bus.Address.High = this.Intermediate.High; + } + protected abstract void Push(byte value); protected abstract byte Pop(); @@ -230,7 +242,12 @@ namespace EightBit return this.GetWord(); } - protected Register16 GetWord(Register16 address) => this.GetWord(address.Word); + protected Register16 GetWord(Register16 address) + { + this.Bus.Address.Low = address.Low; + this.Bus.Address.High = address.High; + return this.GetWord(); + } protected void SetWord(ushort address, Register16 value) { @@ -238,16 +255,33 @@ namespace EightBit this.SetWord(value); } - protected void SetWord(Register16 address, Register16 value) => this.SetWord(address.Word, value); + protected void SetWord(Register16 address, Register16 value) + { + this.Bus.Address.Low = address.Low; + this.Bus.Address.High = address.High; + this.SetWord(value); + } protected void Jump(ushort destination) => this.PC.Word = destination; - protected virtual void Call(ushort destination) + protected void Jump(Register16 destination) + { + this.PC.Low = destination.Low; + this.PC.High = destination.High; + } + + protected void Call(ushort destination) + { + this.Intermediate.Word = destination; + this.Call(this.Intermediate); + } + + protected virtual void Call(Register16 destination) { this.PushWord(this.PC); this.Jump(destination); } - protected virtual void Return() => this.Jump(this.PopWord().Word); + protected virtual void Return() => this.Jump(this.PopWord()); } } diff --git a/Intel8080/Intel8080.cs b/Intel8080/Intel8080.cs index e242018..d992df2 100644 --- a/Intel8080/Intel8080.cs +++ b/Intel8080/Intel8080.cs @@ -499,7 +499,7 @@ namespace EightBit switch (y) { case 0: // JP nn - this.Jump(this.FetchWord().Word); + this.JumpIndirect(); this.Tick(10); break; case 2: // OUT (n),A @@ -548,7 +548,7 @@ namespace EightBit switch (p) { case 0: // CALL nn - this.Call(this.FetchWord().Word); + this.CallIndirect(); this.Tick(17); break; } diff --git a/LR35902/LR35902.cs b/LR35902/LR35902.cs index d7ecaeb..9205006 100644 --- a/LR35902/LR35902.cs +++ b/LR35902/LR35902.cs @@ -746,7 +746,7 @@ namespace EightBit.GameBoy switch (y) { case 0: // JP nn - this.Jump(this.FetchWord().Word); + this.JumpIndirect(); this.Tick(4); break; case 1: // CB prefix @@ -786,7 +786,7 @@ namespace EightBit.GameBoy switch (p) { case 0: // CALL nn - this.Call(this.FetchWord().Word); + this.CallIndirect(); this.Tick(6); break; } diff --git a/M6502/M6502Core.cs b/M6502/M6502Core.cs index 1441095..b3dee76 100644 --- a/M6502/M6502Core.cs +++ b/M6502/M6502Core.cs @@ -233,7 +233,7 @@ namespace EightBit this.Push((byte)(this.P | (source == InterruptSource.hardware ? 0 : (byte)StatusBits.BF))); } this.SetFlag(StatusBits.IF); // Disable IRQ - this.Jump(this.GetWordPaged(0xff, vector).Word); + this.Jump(this.GetWordPaged(0xff, vector)); } #region Interrupt etc. handlers @@ -341,7 +341,7 @@ namespace EightBit #region Cycle wastage - protected void SwallowRead() => this.MemoryRead(this.PC.Word); + protected void SwallowRead() => this.MemoryRead(this.PC); protected void SwallowPop() => this.MemoryRead(this.S, 1); @@ -408,7 +408,7 @@ namespace EightBit case 0x48: this.SwallowRead(); this.Push(this.A); break; // PHA (implied) case 0x49: this.ImmediateRead(); this.EorR(); break; // EOR (immediate) case 0x4a: this.SwallowRead(); this.A = this.LSR(this.A); break; // LSR A (implied) - case 0x4c: this.AbsoluteAddress(); this.Jump(this.Bus.Address.Word); break; // JMP (absolute) + case 0x4c: this.AbsoluteAddress(); this.Jump(this.Bus.Address); break; // JMP (absolute) case 0x4d: this.AbsoluteRead(); this.EorR(); break; // EOR (absolute) case 0x4e: this.AbsoluteRead(); this.ModifyWrite(this.LSR()); break; // LSR (absolute) @@ -428,7 +428,7 @@ namespace EightBit case 0x68: this.SwallowRead(); this.SwallowPop(); this.A = this.Through(this.Pop()); break; // PLA (implied) case 0x69: this.ImmediateRead(); this.ADC(); break; // ADC (immediate) case 0x6a: this.SwallowRead(); this.A = this.ROR(this.A); break; // ROR A (implied) - case 0x6c: this.IndirectAddress(); this.Jump(this.Bus.Address.Word); break; // JMP (indirect) + case 0x6c: this.IndirectAddress(); this.Jump(this.Bus.Address); break; // JMP (indirect) case 0x6d: this.AbsoluteRead(); this.ADC(); break; // ADC (absolute) case 0x6e: this.AbsoluteRead(); this.ModifyWrite(this.ROR()); break; // ROR (absolute) @@ -718,9 +718,14 @@ namespace EightBit this.Bus.Address.Low = this.Intermediate.Low; } - protected void ImmediateAddress() => this.Bus.Address.Word = this.PC.Word++; + protected void ImmediateAddress() + { + this.Bus.Address.Low = this.PC.Low; + this.Bus.Address.High = this.PC.High; + ++this.PC.Word; + } - protected void AbsoluteAddress() => this.Bus.Address.Word = this.FetchWord().Word; + protected void AbsoluteAddress() => this.FetchWordAddress(); protected void ZeroPageAddress() { @@ -731,13 +736,17 @@ namespace EightBit protected void ZeroPageIndirectAddress() { this.ZeroPageAddress(); - this.Bus.Address.Word = this.GetWordPaged().Word; + this.GetWordPaged(); + this.Bus.Address.Low = this.Intermediate.Low; + this.Bus.Address.High = this.Intermediate.High; } protected void IndirectAddress() { this.AbsoluteAddress(); - this.Bus.Address.Word = this.GetWordPaged().Word; + this.GetWordPaged(); + this.Bus.Address.Low = this.Intermediate.Low; + this.Bus.Address.High = this.Intermediate.High; } protected void ZeroPageWithIndexAddress(byte index) @@ -763,7 +772,9 @@ namespace EightBit protected void IndexedIndirectXAddress() { this.ZeroPageXAddress(); - this.Bus.Address.Word = this.GetWordPaged().Word; + this.GetWordPaged(); + this.Bus.Address.Low = this.Intermediate.Low; + this.Bus.Address.High = this.Intermediate.High; } protected void IndirectIndexedYAddress() @@ -849,7 +860,7 @@ namespace EightBit this.SwallowRead(); this.NoteFixedAddress(this.PC.Word + relative); this.MaybeFixup(); - this.Jump(this.Bus.Address.Word); + this.Jump(this.Bus.Address); } } diff --git a/MC6809/MC6809.cs b/MC6809/MC6809.cs index e052e33..6f6ae65 100644 --- a/MC6809/MC6809.cs +++ b/MC6809/MC6809.cs @@ -753,9 +753,7 @@ namespace EightBit private Register16 ST(Register16 data) => this.Through(data); - private void Jump(Register16 destination) => this.Jump(destination.Word); - - private bool Branch(ushort destination, bool condition) + private bool Branch(Register16 destination, bool condition) { if (condition) { @@ -765,8 +763,6 @@ namespace EightBit return condition; } - private bool Branch(Register16 destination, bool condition) => this.Branch(destination.Word, condition); - private void BranchShort(bool condition) => this.Branch(this.Address_relative_byte(), condition); private void BranchLong(bool condition) @@ -1431,9 +1427,7 @@ namespace EightBit return result; } - private void JSR(ushort address) => this.Call(address); - - private void JSR(Register16 address) => this.JSR(address.Word); + private void JSR(Register16 address) => this.Call(address); private byte LSR(byte operand) { diff --git a/Z80/Z80.cs b/Z80/Z80.cs index 8d2835d..a78b987 100644 --- a/Z80/Z80.cs +++ b/Z80/Z80.cs @@ -539,14 +539,14 @@ namespace EightBit this.Tick(7); this.MEMPTR.Low = data; this.MEMPTR.High = this.IV; - this.Call(this.MEMPTR.Word); + this.Call(this.MEMPTR); break; default: throw new NotSupportedException("Invalid interrupt mode"); } } - protected override void Call(ushort destination) + protected override void Call(Register16 destination) { this.Tick(); base.Call(destination); @@ -715,7 +715,7 @@ namespace EightBit this.L = value; break; case 6: - this.MemoryWrite(this.HL.Word, value); + this.MemoryWrite(this.HL, value); break; case 7: this.A = value; @@ -803,7 +803,8 @@ namespace EightBit switch (z) { case 0: // Input from port with 16-bit address - this.MEMPTR.Word = this.Bus.Address.Word = this.BC.Word; + this.MEMPTR.Low = this.Bus.Address.Low = this.BC.Low; + this.MEMPTR.High = this.Bus.Address.High = this.BC.High; this.MEMPTR.Word++; this.ReadPort(); if (y != 6) @@ -815,7 +816,8 @@ namespace EightBit this.F = ClearBit(this.F, StatusBits.NF | StatusBits.HC); break; case 1: // Output to port with 16-bit address - this.MEMPTR.Word = this.Bus.Address.Word = this.BC.Word; + this.MEMPTR.Low = this.Bus.Address.Low = this.BC.Low; + this.MEMPTR.High = this.Bus.Address.High = this.BC.High; this.MEMPTR.Word++; this.Bus.Data = y != 6 ? this.R(y) : (byte)0; this.WritePort(); @@ -829,7 +831,7 @@ namespace EightBit }; break; case 3: // Retrieve/store register pair from/to immediate address - this.Bus.Address.Word = this.FetchWord().Word; + this.FetchWordAddress(); switch (q) { case 0: // LD (nn), rp[p] @@ -920,7 +922,9 @@ namespace EightBit case 6: // LDIR if (this.LDIR()) { - this.MEMPTR.Word = --this.PC.Word; + --this.PC.Word; + this.MEMPTR.Low = this.PC.Low; + this.MEMPTR.High = this.PC.High; --this.PC.Word; } @@ -929,7 +933,9 @@ namespace EightBit case 7: // LDDR if (this.LDDR()) { - this.MEMPTR.Word = --this.PC.Word; + --this.PC.Word; + this.MEMPTR.Low = this.PC.Low; + this.MEMPTR.High = this.PC.High; --this.PC.Word; } @@ -950,7 +956,9 @@ namespace EightBit case 6: // CPIR if (this.CPIR()) { - this.MEMPTR.Word = --this.PC.Word; + --this.PC.Word; + this.MEMPTR.Low = this.PC.Low; + this.MEMPTR.High = this.PC.High; --this.PC.Word; this.Tick(5); } @@ -960,7 +968,9 @@ namespace EightBit case 7: // CPDR if (this.CPDR()) { - this.MEMPTR.Word = --this.PC.Word; + --this.PC.Word; + this.MEMPTR.Low = this.PC.Low; + this.MEMPTR.High = this.PC.High; --this.PC.Word; this.Tick(3); } @@ -1099,23 +1109,27 @@ namespace EightBit switch (p) { case 0: // LD (BC),A - this.MEMPTR.Word = this.Bus.Address.Word = this.BC.Word; + this.MEMPTR.Low = this.Bus.Address.Low = this.BC.Low; + this.MEMPTR.High = this.Bus.Address.High = this.BC.High; ++this.MEMPTR.Word; this.MEMPTR.High = this.Bus.Data = this.A; this.MemoryWrite(); break; case 1: // LD (DE),A - this.MEMPTR.Word = this.Bus.Address.Word = this.DE.Word; + this.MEMPTR.Low = this.Bus.Address.Low = this.DE.Low; + this.MEMPTR.High = this.Bus.Address.High = this.DE.High; ++this.MEMPTR.Word; this.MEMPTR.High = this.Bus.Data = this.A; this.MemoryWrite(); break; case 2: // LD (nn),HL - this.Bus.Address.Word = this.FetchWord().Word; + this.FetchWordAddress(); this.SetWord(this.HL2()); break; case 3: // LD (nn),A - this.MEMPTR.Word = this.Bus.Address.Word = this.FetchWord().Word; + this.FetchWordMEMPTR(); + this.Bus.Address.Low = this.MEMPTR.Low; + this.Bus.Address.High = this.MEMPTR.High; ++this.MEMPTR.Word; this.MEMPTR.High = this.Bus.Data = this.A; this.MemoryWrite(); @@ -1129,21 +1143,25 @@ namespace EightBit switch (p) { case 0: // LD A,(BC) - this.MEMPTR.Word = this.Bus.Address.Word = this.BC.Word; + this.MEMPTR.Low = this.Bus.Address.Low = this.BC.Low; + this.MEMPTR.High = this.Bus.Address.High = this.BC.High; ++this.MEMPTR.Word; this.A = this.MemoryRead(); break; case 1: // LD A,(DE) - this.MEMPTR.Word = this.Bus.Address.Word = this.DE.Word; + this.MEMPTR.Low = this.Bus.Address.Low = this.DE.Low; + this.MEMPTR.High = this.Bus.Address.High = this.DE.High; ++this.MEMPTR.Word; this.A = this.MemoryRead(); break; case 2: // LD HL,(nn) - this.Bus.Address.Word = this.FetchWord().Word; + this.FetchWordAddress(); this.HL2().Word = this.GetWord().Word; break; case 3: // LD A,(nn) - this.MEMPTR.Word = this.Bus.Address.Word = this.FetchWord().Word; + this.FetchWordMEMPTR(); + this.Bus.Address.Low = this.MEMPTR.Low; + this.Bus.Address.High = this.MEMPTR.High; ++this.MEMPTR.Word; this.A = this.MemoryRead(); break; @@ -1395,7 +1413,7 @@ namespace EightBit this.Exx(); break; case 2: // JP HL - this.Jump(this.HL2().Word); + this.Jump(this.HL2()); break; case 3: // LD SP,HL this.SP.Word = this.HL2().Word; @@ -1417,7 +1435,7 @@ namespace EightBit switch (y) { case 0: // JP nn - this.Jump(this.MEMPTR.Word = this.FetchWord().Word); + this.JumpIndirect(); break; case 1: // CB prefix this.prefixCB = true; @@ -1469,8 +1487,7 @@ namespace EightBit switch (p) { case 0: // CALL nn - this.MEMPTR.Word = this.FetchWord().Word; - this.Call(this.MEMPTR.Word); + this.CallIndirect(); break; case 1: // DD prefix this.displaced = this.prefixDD = true; @@ -1578,7 +1595,7 @@ namespace EightBit { this.Tick(); this.LowerM1(); - var returned = this.MemoryRead(this.PC.Word); + var returned = this.MemoryRead(this.PC); this.RaiseM1(); this.Bus.Address.Low = this.REFRESH; this.Bus.Address.High = this.IV; @@ -1911,7 +1928,7 @@ namespace EightBit private void XHTL(Register16 exchange) { - this.MEMPTR.Low = this.MemoryRead(this.SP.Word); + this.MEMPTR.Low = this.MemoryRead(this.SP); ++this.Bus.Address.Word; this.MEMPTR.High = this.MemoryRead(); this.Tick();