Sync (as far as possible) with unmanaged C++ emulators.

Signed-off-by: Adrian Conlon <Adrian.conlon@gmail.com>
This commit is contained in:
Adrian Conlon 2019-10-31 23:01:47 +00:00
parent 8ce71f8ab8
commit 0f2a69509b
4 changed files with 373 additions and 91 deletions

View File

@ -23,6 +23,7 @@ namespace EightBit
private PinLevel soLine = PinLevel.Low; private PinLevel soLine = PinLevel.Low;
private PinLevel syncLine = PinLevel.Low; private PinLevel syncLine = PinLevel.Low;
private PinLevel rdyLine = PinLevel.Low; private PinLevel rdyLine = PinLevel.Low;
private PinLevel rwLine = PinLevel.Low;
public M6502(Bus bus) public M6502(Bus bus)
: base(bus) : base(bus)
@ -65,6 +66,14 @@ namespace EightBit
public event EventHandler<EventArgs> LoweredRDY; public event EventHandler<EventArgs> LoweredRDY;
public event EventHandler<EventArgs> RaisingRW;
public event EventHandler<EventArgs> RaisedRW;
public event EventHandler<EventArgs> LoweringRW;
public event EventHandler<EventArgs> LoweredRW;
public ref PinLevel NMI => ref this.nmiLine; public ref PinLevel NMI => ref this.nmiLine;
public ref PinLevel SO => ref this.soLine; public ref PinLevel SO => ref this.soLine;
@ -73,6 +82,8 @@ namespace EightBit
public ref PinLevel RDY => ref this.rdyLine; public ref PinLevel RDY => ref this.rdyLine;
public ref PinLevel RW => ref this.rwLine;
public byte X { get; set; } = 0; public byte X { get; set; } = 0;
public byte Y { get; set; } = 0; public byte Y { get; set; } = 0;
@ -155,6 +166,26 @@ namespace EightBit
} }
} }
public virtual void RaiseRW()
{
if (this.RW.Lowered())
{
this.OnRaisingRW();
this.RW.Raise();
this.OnRaisedRW();
}
}
public virtual void LowerRW()
{
if (this.RW.Raised())
{
this.OnLoweringRW();
this.RW.Lower();
this.OnLoweredRW();
}
}
public override int Execute() public override int Execute()
{ {
this.RaiseSYNC(); // Instruction fetch has now completed this.RaiseSYNC(); // Instruction fetch has now completed
@ -451,6 +482,7 @@ namespace EightBit
if (this.RDY.Raised()) if (this.RDY.Raised())
{ {
this.LowerSYNC(); // Instruction fetch beginning this.LowerSYNC(); // Instruction fetch beginning
this.RaiseRW();
this.OpCode = this.Bus.Read(this.PC.Word++); // can't use fetchByte this.OpCode = this.Bus.Read(this.PC.Word++); // can't use fetchByte
if (this.RESET.Lowered()) if (this.RESET.Lowered())
{ {
@ -509,6 +541,14 @@ namespace EightBit
protected virtual void OnLoweredRDY() => this.LoweredRDY?.Invoke(this, EventArgs.Empty); protected virtual void OnLoweredRDY() => this.LoweredRDY?.Invoke(this, EventArgs.Empty);
protected virtual void OnRaisingRW() => this.RaisingRW?.Invoke(this, EventArgs.Empty);
protected virtual void OnRaisedRW() => this.RaisedRW?.Invoke(this, EventArgs.Empty);
protected virtual void OnLoweringRW() => this.LoweringRW?.Invoke(this, EventArgs.Empty);
protected virtual void OnLoweredRW() => this.LoweredRW?.Invoke(this, EventArgs.Empty);
protected override void OnRaisedPOWER() protected override void OnRaisedPOWER()
{ {
this.X = (byte)Bits.Bit7; this.X = (byte)Bits.Bit7;
@ -517,6 +557,7 @@ namespace EightBit
this.P = (byte)StatusBits.RF; this.P = (byte)StatusBits.RF;
this.S = (byte)Mask.Mask8; this.S = (byte)Mask.Mask8;
this.LowerSYNC(); this.LowerSYNC();
this.LowerRW();
base.OnRaisedPOWER(); base.OnRaisedPOWER();
} }
@ -555,12 +596,14 @@ namespace EightBit
protected override sealed void BusWrite() protected override sealed void BusWrite()
{ {
this.Tick(); this.Tick();
this.LowerRW();
base.BusWrite(); base.BusWrite();
} }
protected override sealed byte BusRead() protected override sealed byte BusRead()
{ {
this.Tick(); this.Tick();
this.RaiseRW();
return base.BusRead(); return base.BusRead();
} }

View File

@ -36,6 +36,7 @@
private PinLevel haltLine = PinLevel.Low; private PinLevel haltLine = PinLevel.Low;
private PinLevel baLine = PinLevel.Low; private PinLevel baLine = PinLevel.Low;
private PinLevel bsLine = PinLevel.Low; private PinLevel bsLine = PinLevel.Low;
private PinLevel rwLine = PinLevel.Low;
private bool prefix10 = false; private bool prefix10 = false;
private bool prefix11 = false; private bool prefix11 = false;
@ -89,6 +90,14 @@
public event EventHandler<EventArgs> LoweredBS; public event EventHandler<EventArgs> LoweredBS;
public event EventHandler<EventArgs> RaisingRW;
public event EventHandler<EventArgs> RaisedRW;
public event EventHandler<EventArgs> LoweringRW;
public event EventHandler<EventArgs> LoweredRW;
public Register16 D { get; } = new Register16(); public Register16 D { get; } = new Register16();
public ref byte A => ref this.D.High; public ref byte A => ref this.D.High;
@ -147,6 +156,8 @@
public ref PinLevel BS => ref this.bsLine; public ref PinLevel BS => ref this.bsLine;
public ref PinLevel RW => ref this.rwLine;
public void Halt() public void Halt()
{ {
--this.PC.Word; --this.PC.Word;
@ -321,10 +332,31 @@
} }
} }
public void RaiseRW()
{
if (this.RW.Lowered())
{
this.OnRaisingRW();
this.RW.Raise();
this.OnRaisedRW();
}
}
public void LowerRW()
{
if (this.RW.Raised())
{
this.OnLoweringRW();
this.RW.Lower();
this.OnLoweredRW();
}
}
protected override void OnRaisedPOWER() protected override void OnRaisedPOWER()
{ {
this.LowerBA(); this.LowerBA();
this.LowerBS(); this.LowerBS();
this.LowerRW();
base.OnRaisedPOWER(); base.OnRaisedPOWER();
} }
@ -356,6 +388,18 @@
protected override void Push(byte value) => this.PushS(value); protected override void Push(byte value) => this.PushS(value);
protected override void BusWrite()
{
this.LowerRW();
base.BusWrite();
}
protected override byte BusRead()
{
this.RaiseRW();
return base.BusRead();
}
private void HandleHALT() private void HandleHALT()
{ {
this.RaiseBA(); this.RaiseBA();
@ -426,6 +470,14 @@
private void OnLoweredBS() => this.LoweredBS?.Invoke(this, EventArgs.Empty); private void OnLoweredBS() => this.LoweredBS?.Invoke(this, EventArgs.Empty);
private void OnRaisingRW() => this.RaisingRW?.Invoke(this, EventArgs.Empty);
private void OnRaisedRW() => this.RaisedRW?.Invoke(this, EventArgs.Empty);
private void OnLoweringRW() => this.LoweringRW?.Invoke(this, EventArgs.Empty);
private void OnLoweredRW() => this.LoweredRW?.Invoke(this, EventArgs.Empty);
private void OnExecutingInstruction() => this.ExecutingInstruction?.Invoke(this, EventArgs.Empty); private void OnExecutingInstruction() => this.ExecutingInstruction?.Invoke(this, EventArgs.Empty);
private void OnExecutedInstruction() => this.ExecutedInstruction?.Invoke(this, EventArgs.Empty); private void OnExecutedInstruction() => this.ExecutedInstruction?.Invoke(this, EventArgs.Empty);

View File

@ -266,6 +266,39 @@ namespace EightBit
dumpCount += 2; dumpCount += 2;
break; break;
case 4: // Negate accumulator
specification = "NEG";
break;
case 5: // Return from interrupt
switch (y)
{
case 1:
specification = "RETI";
break;
default:
specification = "RETN";
break;
}
break;
case 6: // Set interrupt mode
switch (y)
{
case 0:
case 1:
case 4:
case 5:
specification = "IM 0";
break;
case 2:
case 6:
specification = "IM 1";
break;
case 3:
case 7:
specification = "IM 2";
break;
}
break;
case 7: case 7:
switch (y) switch (y)
{ {

View File

@ -31,6 +31,9 @@ namespace EightBit
private PinLevel nmiLine = PinLevel.Low; private PinLevel nmiLine = PinLevel.Low;
private PinLevel m1Line = PinLevel.Low; private PinLevel m1Line = PinLevel.Low;
private PinLevel iorqLine = PinLevel.Low;
private PinLevel rdLine = PinLevel.Low;
private PinLevel wrLine = PinLevel.Low;
private int accumulatorFlagsSet = 0; private int accumulatorFlagsSet = 0;
@ -61,6 +64,30 @@ namespace EightBit
public event EventHandler<EventArgs> LoweredM1; public event EventHandler<EventArgs> LoweredM1;
public event EventHandler<EventArgs> RaisingIORQ;
public event EventHandler<EventArgs> RaisedIORQ;
public event EventHandler<EventArgs> LoweringIORQ;
public event EventHandler<EventArgs> LoweredIORQ;
public event EventHandler<EventArgs> RaisingRD;
public event EventHandler<EventArgs> RaisedRD;
public event EventHandler<EventArgs> LoweringRD;
public event EventHandler<EventArgs> LoweredRD;
public event EventHandler<EventArgs> RaisingWR;
public event EventHandler<EventArgs> RaisedWR;
public event EventHandler<EventArgs> LoweringWR;
public event EventHandler<EventArgs> LoweredWR;
public byte IV { get; set; } = 0xff; public byte IV { get; set; } = 0xff;
public int IM { get; set; } = 0; public int IM { get; set; } = 0;
@ -95,6 +122,12 @@ namespace EightBit
public ref PinLevel M1 => ref this.m1Line; public ref PinLevel M1 => ref this.m1Line;
public ref PinLevel IORQ => ref this.iorqLine;
public ref PinLevel RD => ref this.rdLine;
public ref PinLevel WR => ref this.wrLine;
private ushort DisplacedAddress private ushort DisplacedAddress
{ {
get get
@ -148,13 +181,69 @@ namespace EightBit
} }
} }
public virtual void RaiseIORQ()
{
if (this.IORQ.Lowered())
{
this.OnRaisingIORQ();
this.IORQ.Raise();
this.OnRaisedIORQ();
}
}
public virtual void LowerIORQ()
{
if (this.IORQ.Raised())
{
this.OnLoweringIORQ();
this.IORQ.Lower();
this.OnLoweredIORQ();
}
}
public virtual void RaiseRD()
{
if (this.RD.Lowered())
{
this.OnRaisingRD();
this.RD.Raise();
this.OnRaisedRD();
}
}
public virtual void LowerRD()
{
if (this.RD.Raised())
{
this.OnLoweringRD();
this.RD.Lower();
this.OnLoweredRD();
}
}
public virtual void RaiseWR()
{
if (this.WR.Lowered())
{
this.OnRaisingWR();
this.WR.Raise();
this.OnRaisedWR();
}
}
public virtual void LowerWR()
{
if (this.WR.Raised())
{
this.OnLoweringWR();
this.WR.Lower();
this.OnLoweredWR();
}
}
public override int Execute() public override int Execute()
{ {
if (!(this.prefixCB && this.displaced)) this.RaiseM1();
{
++this.REFRESH;
this.RaiseM1();
}
var decoded = this.GetDecodedOpCode(this.OpCode); var decoded = this.GetDecodedOpCode(this.OpCode);
@ -165,17 +254,13 @@ namespace EightBit
var p = decoded.P; var p = decoded.P;
var q = decoded.Q; var q = decoded.Q;
var prefixed = this.prefixCB || this.prefixED; if (this.prefixCB)
if (prefixed)
{ {
if (this.prefixCB) this.ExecuteCB(x, y, z);
{ }
this.ExecuteCB(x, y, z); else if (this.prefixED)
} {
else if (this.prefixED) this.ExecuteED(x, y, z, p, q);
{
this.ExecuteED(x, y, z, p, q);
}
} }
else else
{ {
@ -192,7 +277,6 @@ namespace EightBit
if (this.Powered) if (this.Powered)
{ {
this.displaced = this.prefixCB = this.prefixDD = this.prefixED = false; this.displaced = this.prefixCB = this.prefixDD = this.prefixED = false;
this.LowerM1();
var handled = false; var handled = false;
if (this.RESET.Lowered()) if (this.RESET.Lowered())
{ {
@ -219,6 +303,7 @@ namespace EightBit
if (!handled) if (!handled)
{ {
this.LowerM1();
this.Execute(this.FetchByte()); this.Execute(this.FetchByte());
} }
} }
@ -230,6 +315,9 @@ namespace EightBit
protected override void OnRaisedPOWER() protected override void OnRaisedPOWER()
{ {
this.RaiseM1(); this.RaiseM1();
this.RaiseIORQ();
this.RaiseRD();
this.RaiseWR();
this.DisableInterrupts(); this.DisableInterrupts();
this.IM = 0; this.IM = 0;
@ -265,7 +353,50 @@ namespace EightBit
protected virtual void OnLoweringM1() => this.LoweringM1?.Invoke(this, EventArgs.Empty); protected virtual void OnLoweringM1() => this.LoweringM1?.Invoke(this, EventArgs.Empty);
protected virtual void OnLoweredM1() => this.LoweredM1?.Invoke(this, EventArgs.Empty); protected virtual void OnLoweredM1()
{
++this.REFRESH;
this.LoweredM1?.Invoke(this, EventArgs.Empty);
}
protected virtual void OnLoweringIORQ() => this.LoweringIORQ?.Invoke(this, EventArgs.Empty);
protected virtual void OnLoweredIORQ() => this.LoweredIORQ?.Invoke(this, EventArgs.Empty);
protected virtual void OnRaisingIORQ() => this.RaisingIORQ?.Invoke(this, EventArgs.Empty);
protected virtual void OnRaisedIORQ() => this.RaisedIORQ?.Invoke(this, EventArgs.Empty);
protected virtual void OnLoweringRD() => this.LoweringRD?.Invoke(this, EventArgs.Empty);
protected virtual void OnLoweredRD() => this.LoweredRD?.Invoke(this, EventArgs.Empty);
protected virtual void OnRaisingRD() => this.RaisingRD?.Invoke(this, EventArgs.Empty);
protected virtual void OnRaisedRD() => this.RaisedRD?.Invoke(this, EventArgs.Empty);
protected virtual void OnLoweringWR() => this.LoweringWR?.Invoke(this, EventArgs.Empty);
protected virtual void OnLoweredWR() => this.LoweredWR?.Invoke(this, EventArgs.Empty);
protected virtual void OnRaisingWR() => this.RaisingWR?.Invoke(this, EventArgs.Empty);
protected virtual void OnRaisedWR() => this.RaisedWR?.Invoke(this, EventArgs.Empty);
protected override void BusWrite()
{
this.LowerWR();
base.BusWrite();
this.RaiseWR();
}
protected override byte BusRead()
{
this.LowerRD();
var returned = base.BusRead();
this.RaiseRD();
return returned;
}
protected override void HandleRESET() protected override void HandleRESET()
{ {
@ -277,18 +408,23 @@ namespace EightBit
protected override void HandleINT() protected override void HandleINT()
{ {
base.HandleINT(); base.HandleINT();
this.LowerM1();
this.LowerIORQ();
var data = this.Bus.Data;
this.RaiseIORQ();
this.RaiseM1();
this.DisableInterrupts(); this.DisableInterrupts();
switch (this.IM) switch (this.IM)
{ {
case 0: // i8080 equivalent case 0: // i8080 equivalent
this.Execute(this.Bus.Data); this.Execute(data);
break; break;
case 1: case 1:
this.Restart(7 << 3); this.Restart(7 << 3);
this.Tick(13); this.Tick(13);
break; break;
case 2: case 2:
this.Call(this.MEMPTR.Word = new Register16(this.Bus.Data, this.IV).Word); this.Call(this.MEMPTR.Word = new Register16(data, this.IV).Word);
this.Tick(19); this.Tick(19);
break; break;
default: default:
@ -639,10 +775,10 @@ namespace EightBit
switch (q) switch (q)
{ {
case 0: // SBC HL, rp[p] case 0: // SBC HL, rp[p]
this.SBC(this.RP(p)); this.HL2().Word = this.SBC(this.HL2(), this.RP(p));
break; break;
case 1: // ADC HL, rp[p] case 1: // ADC HL, rp[p]
this.ADC(this.RP(p)); this.HL2().Word = this.ADC(this.HL2(), this.RP(p));
break; break;
default: default:
throw new NotSupportedException("Invalid operation mode"); throw new NotSupportedException("Invalid operation mode");
@ -894,6 +1030,11 @@ namespace EightBit
switch (y) switch (y)
{ {
case 0: // NOP case 0: // NOP
if (this.prefixDD)
{
this.Tick(4);
}
this.Tick(4); this.Tick(4);
break; break;
case 1: // EX AF AF' case 1: // EX AF AF'
@ -936,7 +1077,7 @@ namespace EightBit
this.Tick(10); this.Tick(10);
break; break;
case 1: // ADD HL,rp case 1: // ADD HL,rp
this.Add(this.RP(p)); this.HL2().Word = this.Add(this.HL2(), this.RP(p));
this.Tick(11); this.Tick(11);
break; break;
default: default:
@ -1180,16 +1321,16 @@ namespace EightBit
switch (y) switch (y)
{ {
case 0: // ADD A,r case 0: // ADD A,r
this.Add(value); this.A = this.Add(this.A, value);
break; break;
case 1: // ADC A,r case 1: // ADC A,r
this.ADC(value); this.A = this.ADC(this.A, value);
break; break;
case 2: // SUB r case 2: // SUB r
this.SUB(value); this.A = this.SUB(this.A, value);
break; break;
case 3: // SBC A,r case 3: // SBC A,r
this.SBC(value); this.A = this.SBC(this.A, value);
break; break;
case 4: // AND r case 4: // AND r
this.AndR(value); this.AndR(value);
@ -1275,8 +1416,11 @@ namespace EightBit
{ {
this.FetchDisplacement(); this.FetchDisplacement();
} }
else
{
this.LowerM1();
}
this.LowerM1();
this.Execute(this.FetchByte()); this.Execute(this.FetchByte());
break; break;
case 2: // OUT (n),A case 2: // OUT (n),A
@ -1361,16 +1505,16 @@ namespace EightBit
switch (y) switch (y)
{ {
case 0: // ADD A,n case 0: // ADD A,n
this.Add(operand); this.A = this.Add(this.A, operand);
break; break;
case 1: // ADC A,n case 1: // ADC A,n
this.ADC(operand); this.A = this.ADC(this.A, operand);
break; break;
case 2: // SUB n case 2: // SUB n
this.SUB(operand); this.A = this.SUB(this.A, operand);
break; break;
case 3: // SBC A,n case 3: // SBC A,n
this.SBC(operand); this.A = this.SBC(this.A, operand);
break; break;
case 4: // AND n case 4: // AND n
this.AndR(operand); this.AndR(operand);
@ -1409,6 +1553,9 @@ namespace EightBit
this.RaiseNMI(); this.RaiseNMI();
this.RaiseHALT(); this.RaiseHALT();
this.IFF1 = false; this.IFF1 = false;
this.LowerM1();
var discarded = this.Bus.Data;
this.RaiseM1();
this.Restart(0x66); this.Restart(0x66);
this.Tick(13); this.Tick(13);
} }
@ -1550,92 +1697,84 @@ namespace EightBit
} }
} }
private void SBC(Register16 value) private ushort SBC(Register16 operand, Register16 value)
{ {
var hl2 = this.HL2(); var subtraction = operand.Word - value.Word - (this.F & (byte)StatusBits.CF);
this.MEMPTR.Word = hl2.Word; this.intermediate.Word = (ushort)subtraction;
var beforeNegative = this.MEMPTR.High & (byte)StatusBits.SF;
var valueNegative = value.High & (byte)StatusBits.SF;
var result = this.MEMPTR.Word - value.Word - (this.F & (byte)StatusBits.CF);
hl2.Word = (ushort)result;
var afterNegative = hl2.High & (byte)StatusBits.SF;
this.F = SetBit(this.F, StatusBits.SF, afterNegative);
this.F = ClearBit(this.F, StatusBits.ZF, hl2.Word);
this.F = AdjustHalfCarrySub(this.F, this.MEMPTR.High, value.High, hl2.High);
this.F = AdjustOverflowSub(this.F, beforeNegative, valueNegative, afterNegative);
this.F = SetBit(this.F, StatusBits.NF); this.F = SetBit(this.F, StatusBits.NF);
this.F = SetBit(this.F, StatusBits.CF, result & (int)Bits.Bit16); this.F = ClearBit(this.F, StatusBits.ZF, this.intermediate.Word);
this.F = AdjustXY(this.F, hl2.High); this.F = SetBit(this.F, StatusBits.CF, subtraction & (int)Bits.Bit16);
this.F = AdjustHalfCarrySub(this.F, operand.High, value.High, this.intermediate.High);
this.F = AdjustXY(this.F, this.intermediate.High);
++this.MEMPTR.Word; var beforeNegative = operand.High & (byte)StatusBits.SF;
}
private void ADC(Register16 value)
{
var hl2 = this.HL2();
this.MEMPTR.Word = hl2.Word;
var beforeNegative = this.MEMPTR.High & (byte)StatusBits.SF;
var valueNegative = value.High & (byte)StatusBits.SF; var valueNegative = value.High & (byte)StatusBits.SF;
var afterNegative = this.intermediate.High & (byte)StatusBits.SF;
var result = this.MEMPTR.Word + value.Word + (this.F & (byte)StatusBits.CF);
hl2.Word = (ushort)result; this.F = SetBit(this.F, StatusBits.SF, afterNegative);
this.F = AdjustOverflowSub(this.F, beforeNegative, valueNegative, afterNegative);
var afterNegative = hl2.High & (byte)StatusBits.SF;
this.MEMPTR.Word = (ushort)(operand.Word + 1);
return this.intermediate.Word;
}
private ushort 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);
var beforeNegative = operand.High & (byte)StatusBits.SF;
var valueNegative = value.High & (byte)StatusBits.SF;
var afterNegative = this.intermediate.High & (byte)StatusBits.SF;
this.F = SetBit(this.F, StatusBits.SF, afterNegative); this.F = SetBit(this.F, StatusBits.SF, afterNegative);
this.F = ClearBit(this.F, StatusBits.ZF, hl2.Word);
this.F = AdjustHalfCarryAdd(this.F, this.MEMPTR.High, value.High, hl2.High);
this.F = AdjustOverflowAdd(this.F, beforeNegative, valueNegative, afterNegative); this.F = AdjustOverflowAdd(this.F, beforeNegative, valueNegative, afterNegative);
this.F = ClearBit(this.F, StatusBits.NF);
this.F = SetBit(this.F, StatusBits.CF, result & (int)Bits.Bit16);
this.F = AdjustXY(this.F, hl2.High);
++this.MEMPTR.Word; return this.intermediate.Word;
} }
private void Add(Register16 value) private ushort Add(Register16 operand, Register16 value, int carry = 0)
{ {
var hl2 = this.HL2(); var addition = operand.Word + value.Word + carry;
this.MEMPTR.Word = hl2.Word; this.intermediate.Word = (ushort)addition;
var result = this.MEMPTR.Word + value.Word;
hl2.Word = (ushort)result;
this.F = ClearBit(this.F, StatusBits.NF); this.F = ClearBit(this.F, StatusBits.NF);
this.F = SetBit(this.F, StatusBits.CF, result & (int)Bits.Bit16); this.F = SetBit(this.F, StatusBits.CF, addition & (int)Bits.Bit16);
this.F = AdjustHalfCarryAdd(this.F, this.MEMPTR.High, value.High, hl2.High); this.F = AdjustHalfCarryAdd(this.F, operand.High, value.High, this.intermediate.High);
this.F = AdjustXY(this.F, hl2.High); this.F = AdjustXY(this.F, this.intermediate.High);
++this.MEMPTR.Word; this.MEMPTR.Word = (ushort)(operand.Word + 1);
return this.intermediate.Word;
} }
private void Add(byte value, int carry = 0) private byte Add(byte operand, byte value, int carry = 0)
{ {
this.intermediate.Word = (ushort)(this.A + value + carry); this.intermediate.Word = (ushort)(operand + value + carry);
var result = this.intermediate.Low;
this.F = AdjustHalfCarryAdd(this.F, this.A, value, this.intermediate.Low); this.F = AdjustHalfCarryAdd(this.F, operand, value, result);
this.F = AdjustOverflowAdd(this.F, this.A, value, this.intermediate.Low); this.F = AdjustOverflowAdd(this.F, operand, value, result);
this.F = ClearBit(this.F, StatusBits.NF); this.F = ClearBit(this.F, StatusBits.NF);
this.F = SetBit(this.F, StatusBits.CF, this.intermediate.High & (byte)StatusBits.CF); this.F = SetBit(this.F, StatusBits.CF, this.intermediate.High & (byte)StatusBits.CF);
this.F = AdjustSZXY(this.F, this.A = this.intermediate.Low); this.F = AdjustSZXY(this.F, result);
return result;
} }
private void ADC(byte value) => this.Add(value, this.F & (byte)StatusBits.CF); private byte ADC(byte operand, byte value) => this.Add(operand, value, this.F & (byte)StatusBits.CF);
private void SUB(byte value, int carry = 0) private byte SUB(byte operand, byte value, int carry = 0)
{ {
this.A = this.Subtract(this.A, value, carry); var subtraction = this.Subtract(operand, value, carry);
this.F = AdjustXY(this.F, this.A); this.F = AdjustXY(this.F, subtraction);
return subtraction;
} }
private void SBC(byte value) => this.SUB(value, this.F & (byte)StatusBits.CF); private byte SBC(byte operand, byte value) => this.SUB(operand, value, this.F & (byte)StatusBits.CF);
private void AndR(byte value) private void AndR(byte value)
{ {
@ -2002,7 +2141,14 @@ namespace EightBit
++this.MEMPTR.Low; ++this.MEMPTR.Low;
} }
private void WritePort() => this.ports.Write(this.Bus.Address.Low, this.Bus.Data); private void WritePort()
{
this.LowerIORQ();
this.LowerWR();
this.ports.Write(this.Bus.Address.Low, this.Bus.Data);
this.RaiseWR();
this.RaiseIORQ();
}
private byte ReadPort(byte port) private byte ReadPort(byte port)
{ {
@ -2011,6 +2157,14 @@ namespace EightBit
return this.ReadPort(); return this.ReadPort();
} }
private byte ReadPort() => this.Bus.Data = this.ports.Read(this.Bus.Address.Low); private byte ReadPort()
{
this.LowerIORQ();
this.LowerRD();
var returned = this.Bus.Data = this.ports.Read(this.Bus.Address.Low);
this.RaiseRD();
this.RaiseIORQ();
return returned;
}
} }
} }