mirror of
https://github.com/MoleskiCoder/EightBitNet.git
synced 2024-12-22 10:30:46 +00:00
Sync (as far as possible) with unmanaged C++ emulators.
Signed-off-by: Adrian Conlon <Adrian.conlon@gmail.com>
This commit is contained in:
parent
8ce71f8ab8
commit
0f2a69509b
@ -23,6 +23,7 @@ namespace EightBit
|
||||
private PinLevel soLine = PinLevel.Low;
|
||||
private PinLevel syncLine = PinLevel.Low;
|
||||
private PinLevel rdyLine = PinLevel.Low;
|
||||
private PinLevel rwLine = PinLevel.Low;
|
||||
|
||||
public M6502(Bus bus)
|
||||
: base(bus)
|
||||
@ -65,6 +66,14 @@ namespace EightBit
|
||||
|
||||
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 SO => ref this.soLine;
|
||||
@ -73,6 +82,8 @@ namespace EightBit
|
||||
|
||||
public ref PinLevel RDY => ref this.rdyLine;
|
||||
|
||||
public ref PinLevel RW => ref this.rwLine;
|
||||
|
||||
public byte X { 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()
|
||||
{
|
||||
this.RaiseSYNC(); // Instruction fetch has now completed
|
||||
@ -451,6 +482,7 @@ namespace EightBit
|
||||
if (this.RDY.Raised())
|
||||
{
|
||||
this.LowerSYNC(); // Instruction fetch beginning
|
||||
this.RaiseRW();
|
||||
this.OpCode = this.Bus.Read(this.PC.Word++); // can't use fetchByte
|
||||
if (this.RESET.Lowered())
|
||||
{
|
||||
@ -509,6 +541,14 @@ namespace EightBit
|
||||
|
||||
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()
|
||||
{
|
||||
this.X = (byte)Bits.Bit7;
|
||||
@ -517,6 +557,7 @@ namespace EightBit
|
||||
this.P = (byte)StatusBits.RF;
|
||||
this.S = (byte)Mask.Mask8;
|
||||
this.LowerSYNC();
|
||||
this.LowerRW();
|
||||
base.OnRaisedPOWER();
|
||||
}
|
||||
|
||||
@ -555,12 +596,14 @@ namespace EightBit
|
||||
protected override sealed void BusWrite()
|
||||
{
|
||||
this.Tick();
|
||||
this.LowerRW();
|
||||
base.BusWrite();
|
||||
}
|
||||
|
||||
protected override sealed byte BusRead()
|
||||
{
|
||||
this.Tick();
|
||||
this.RaiseRW();
|
||||
return base.BusRead();
|
||||
}
|
||||
|
||||
|
@ -36,6 +36,7 @@
|
||||
private PinLevel haltLine = PinLevel.Low;
|
||||
private PinLevel baLine = PinLevel.Low;
|
||||
private PinLevel bsLine = PinLevel.Low;
|
||||
private PinLevel rwLine = PinLevel.Low;
|
||||
|
||||
private bool prefix10 = false;
|
||||
private bool prefix11 = false;
|
||||
@ -89,6 +90,14 @@
|
||||
|
||||
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 ref byte A => ref this.D.High;
|
||||
@ -147,6 +156,8 @@
|
||||
|
||||
public ref PinLevel BS => ref this.bsLine;
|
||||
|
||||
public ref PinLevel RW => ref this.rwLine;
|
||||
|
||||
public void Halt()
|
||||
{
|
||||
--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()
|
||||
{
|
||||
this.LowerBA();
|
||||
this.LowerBS();
|
||||
this.LowerRW();
|
||||
base.OnRaisedPOWER();
|
||||
}
|
||||
|
||||
@ -356,6 +388,18 @@
|
||||
|
||||
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()
|
||||
{
|
||||
this.RaiseBA();
|
||||
@ -426,6 +470,14 @@
|
||||
|
||||
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 OnExecutedInstruction() => this.ExecutedInstruction?.Invoke(this, EventArgs.Empty);
|
||||
|
@ -266,6 +266,39 @@ namespace EightBit
|
||||
|
||||
dumpCount += 2;
|
||||
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:
|
||||
switch (y)
|
||||
{
|
||||
|
336
Z80/Z80.cs
336
Z80/Z80.cs
@ -31,6 +31,9 @@ namespace EightBit
|
||||
|
||||
private PinLevel nmiLine = 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;
|
||||
|
||||
@ -61,6 +64,30 @@ namespace EightBit
|
||||
|
||||
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 int IM { get; set; } = 0;
|
||||
@ -95,6 +122,12 @@ namespace EightBit
|
||||
|
||||
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
|
||||
{
|
||||
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()
|
||||
{
|
||||
if (!(this.prefixCB && this.displaced))
|
||||
{
|
||||
++this.REFRESH;
|
||||
this.RaiseM1();
|
||||
}
|
||||
this.RaiseM1();
|
||||
|
||||
var decoded = this.GetDecodedOpCode(this.OpCode);
|
||||
|
||||
@ -165,17 +254,13 @@ namespace EightBit
|
||||
var p = decoded.P;
|
||||
var q = decoded.Q;
|
||||
|
||||
var prefixed = this.prefixCB || this.prefixED;
|
||||
if (prefixed)
|
||||
if (this.prefixCB)
|
||||
{
|
||||
if (this.prefixCB)
|
||||
{
|
||||
this.ExecuteCB(x, y, z);
|
||||
}
|
||||
else if (this.prefixED)
|
||||
{
|
||||
this.ExecuteED(x, y, z, p, q);
|
||||
}
|
||||
this.ExecuteCB(x, y, z);
|
||||
}
|
||||
else if (this.prefixED)
|
||||
{
|
||||
this.ExecuteED(x, y, z, p, q);
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -192,7 +277,6 @@ namespace EightBit
|
||||
if (this.Powered)
|
||||
{
|
||||
this.displaced = this.prefixCB = this.prefixDD = this.prefixED = false;
|
||||
this.LowerM1();
|
||||
var handled = false;
|
||||
if (this.RESET.Lowered())
|
||||
{
|
||||
@ -219,6 +303,7 @@ namespace EightBit
|
||||
|
||||
if (!handled)
|
||||
{
|
||||
this.LowerM1();
|
||||
this.Execute(this.FetchByte());
|
||||
}
|
||||
}
|
||||
@ -230,6 +315,9 @@ namespace EightBit
|
||||
protected override void OnRaisedPOWER()
|
||||
{
|
||||
this.RaiseM1();
|
||||
this.RaiseIORQ();
|
||||
this.RaiseRD();
|
||||
this.RaiseWR();
|
||||
|
||||
this.DisableInterrupts();
|
||||
this.IM = 0;
|
||||
@ -265,7 +353,50 @@ namespace EightBit
|
||||
|
||||
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()
|
||||
{
|
||||
@ -277,18 +408,23 @@ namespace EightBit
|
||||
protected override void HandleINT()
|
||||
{
|
||||
base.HandleINT();
|
||||
this.LowerM1();
|
||||
this.LowerIORQ();
|
||||
var data = this.Bus.Data;
|
||||
this.RaiseIORQ();
|
||||
this.RaiseM1();
|
||||
this.DisableInterrupts();
|
||||
switch (this.IM)
|
||||
{
|
||||
case 0: // i8080 equivalent
|
||||
this.Execute(this.Bus.Data);
|
||||
this.Execute(data);
|
||||
break;
|
||||
case 1:
|
||||
this.Restart(7 << 3);
|
||||
this.Tick(13);
|
||||
break;
|
||||
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);
|
||||
break;
|
||||
default:
|
||||
@ -639,10 +775,10 @@ namespace EightBit
|
||||
switch (q)
|
||||
{
|
||||
case 0: // SBC HL, rp[p]
|
||||
this.SBC(this.RP(p));
|
||||
this.HL2().Word = this.SBC(this.HL2(), this.RP(p));
|
||||
break;
|
||||
case 1: // ADC HL, rp[p]
|
||||
this.ADC(this.RP(p));
|
||||
this.HL2().Word = this.ADC(this.HL2(), this.RP(p));
|
||||
break;
|
||||
default:
|
||||
throw new NotSupportedException("Invalid operation mode");
|
||||
@ -894,6 +1030,11 @@ namespace EightBit
|
||||
switch (y)
|
||||
{
|
||||
case 0: // NOP
|
||||
if (this.prefixDD)
|
||||
{
|
||||
this.Tick(4);
|
||||
}
|
||||
|
||||
this.Tick(4);
|
||||
break;
|
||||
case 1: // EX AF AF'
|
||||
@ -936,7 +1077,7 @@ namespace EightBit
|
||||
this.Tick(10);
|
||||
break;
|
||||
case 1: // ADD HL,rp
|
||||
this.Add(this.RP(p));
|
||||
this.HL2().Word = this.Add(this.HL2(), this.RP(p));
|
||||
this.Tick(11);
|
||||
break;
|
||||
default:
|
||||
@ -1180,16 +1321,16 @@ namespace EightBit
|
||||
switch (y)
|
||||
{
|
||||
case 0: // ADD A,r
|
||||
this.Add(value);
|
||||
this.A = this.Add(this.A, value);
|
||||
break;
|
||||
case 1: // ADC A,r
|
||||
this.ADC(value);
|
||||
this.A = this.ADC(this.A, value);
|
||||
break;
|
||||
case 2: // SUB r
|
||||
this.SUB(value);
|
||||
this.A = this.SUB(this.A, value);
|
||||
break;
|
||||
case 3: // SBC A,r
|
||||
this.SBC(value);
|
||||
this.A = this.SBC(this.A, value);
|
||||
break;
|
||||
case 4: // AND r
|
||||
this.AndR(value);
|
||||
@ -1275,8 +1416,11 @@ namespace EightBit
|
||||
{
|
||||
this.FetchDisplacement();
|
||||
}
|
||||
else
|
||||
{
|
||||
this.LowerM1();
|
||||
}
|
||||
|
||||
this.LowerM1();
|
||||
this.Execute(this.FetchByte());
|
||||
break;
|
||||
case 2: // OUT (n),A
|
||||
@ -1361,16 +1505,16 @@ namespace EightBit
|
||||
switch (y)
|
||||
{
|
||||
case 0: // ADD A,n
|
||||
this.Add(operand);
|
||||
this.A = this.Add(this.A, operand);
|
||||
break;
|
||||
case 1: // ADC A,n
|
||||
this.ADC(operand);
|
||||
this.A = this.ADC(this.A, operand);
|
||||
break;
|
||||
case 2: // SUB n
|
||||
this.SUB(operand);
|
||||
this.A = this.SUB(this.A, operand);
|
||||
break;
|
||||
case 3: // SBC A,n
|
||||
this.SBC(operand);
|
||||
this.A = this.SBC(this.A, operand);
|
||||
break;
|
||||
case 4: // AND n
|
||||
this.AndR(operand);
|
||||
@ -1409,6 +1553,9 @@ namespace EightBit
|
||||
this.RaiseNMI();
|
||||
this.RaiseHALT();
|
||||
this.IFF1 = false;
|
||||
this.LowerM1();
|
||||
var discarded = this.Bus.Data;
|
||||
this.RaiseM1();
|
||||
this.Restart(0x66);
|
||||
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();
|
||||
this.MEMPTR.Word = hl2.Word;
|
||||
var subtraction = operand.Word - value.Word - (this.F & (byte)StatusBits.CF);
|
||||
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.CF, result & (int)Bits.Bit16);
|
||||
this.F = AdjustXY(this.F, hl2.High);
|
||||
this.F = ClearBit(this.F, StatusBits.ZF, this.intermediate.Word);
|
||||
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;
|
||||
}
|
||||
|
||||
private void ADC(Register16 value)
|
||||
{
|
||||
var hl2 = this.HL2();
|
||||
this.MEMPTR.Word = hl2.Word;
|
||||
|
||||
var beforeNegative = this.MEMPTR.High & (byte)StatusBits.SF;
|
||||
var beforeNegative = operand.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;
|
||||
var afterNegative = this.intermediate.High & (byte)StatusBits.SF;
|
||||
|
||||
this.F = SetBit(this.F, StatusBits.SF, afterNegative);
|
||||
this.F = AdjustOverflowSub(this.F, beforeNegative, valueNegative, afterNegative);
|
||||
|
||||
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 = 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 = 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();
|
||||
this.MEMPTR.Word = hl2.Word;
|
||||
|
||||
var result = this.MEMPTR.Word + value.Word;
|
||||
|
||||
hl2.Word = (ushort)result;
|
||||
var addition = operand.Word + value.Word + carry;
|
||||
this.intermediate.Word = (ushort)addition;
|
||||
|
||||
this.F = ClearBit(this.F, StatusBits.NF);
|
||||
this.F = SetBit(this.F, StatusBits.CF, result & (int)Bits.Bit16);
|
||||
this.F = AdjustHalfCarryAdd(this.F, this.MEMPTR.High, value.High, hl2.High);
|
||||
this.F = AdjustXY(this.F, hl2.High);
|
||||
this.F = SetBit(this.F, StatusBits.CF, addition & (int)Bits.Bit16);
|
||||
this.F = AdjustHalfCarryAdd(this.F, operand.High, value.High, this.intermediate.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 = AdjustOverflowAdd(this.F, this.A, value, this.intermediate.Low);
|
||||
this.F = AdjustHalfCarryAdd(this.F, operand, value, result);
|
||||
this.F = AdjustOverflowAdd(this.F, operand, value, result);
|
||||
|
||||
this.F = ClearBit(this.F, StatusBits.NF);
|
||||
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);
|
||||
this.F = AdjustXY(this.F, this.A);
|
||||
var subtraction = this.Subtract(operand, value, carry);
|
||||
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)
|
||||
{
|
||||
@ -2002,7 +2141,14 @@ namespace EightBit
|
||||
++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)
|
||||
{
|
||||
@ -2011,6 +2157,14 @@ namespace EightBit
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user