diff --git a/Intel8080/Intel8080.cs b/Intel8080/Intel8080.cs index 1bd65fd..b0b9553 100644 --- a/Intel8080/Intel8080.cs +++ b/Intel8080/Intel8080.cs @@ -85,8 +85,9 @@ namespace Intel8080 this.OnReadingMemory(); this.Tick(2); base.MemoryRead(); + this.Tick(); this.OnReadMemory(); - this.Tick(2); + this.Tick(); return this.Bus.Data; } @@ -103,6 +104,14 @@ namespace Intel8080 return this.Bus.Data; } + protected override void HandleINT() + { + base.HandleINT(); + var data = this.ReadDataUnderInterrupt(); + this.Tick(); + this.Execute(data); + } + protected override void Call(Register16 destination) { this.Tick(); @@ -115,14 +124,6 @@ namespace Intel8080 this.Tick(5); } - protected override void HandleINT() - { - base.HandleINT(); - var data = this.ReadDataUnderInterrupt(); - this.Tick(); - this.Execute(data); - } - private int Zero() => ZeroTest(this.F); private int Carry() => CarryTest(this.F); @@ -145,14 +146,24 @@ namespace Intel8080 private static byte SetBit(byte f, StatusBits flag) => SetBit(f, (byte)flag); + private void SetBit(StatusBits flag) => this.F = SetBit(this.F, flag); + private static byte SetBit(byte f, StatusBits flag, int condition) => SetBit(f, (byte)flag, condition); + private void SetBit(StatusBits flag, int condition) => this.F = SetBit(this.F, flag, condition); + private static byte SetBit(byte f, StatusBits flag, bool condition) => SetBit(f, (byte)flag, condition); + private void SetBit(StatusBits flag, bool condition) => this.F = SetBit(this.F, flag, condition); + private static byte ClearBit(byte f, StatusBits flag) => ClearBit(f, (byte)flag); + private void ClearBit(StatusBits flag) => this.F = ClearBit(this.F, flag); + private static byte ClearBit(byte f, StatusBits flag, int condition) => ClearBit(f, (byte)flag, condition); + private void ClearBit(StatusBits flag, int condition) => this.F = ClearBit(this.F, flag, condition); + private static byte AdjustSign(byte input, byte value) => SetBit(input, StatusBits.SF, SignTest(value)); private static byte AdjustZero(byte input, byte value) => ClearBit(input, StatusBits.ZF, value); @@ -171,14 +182,38 @@ namespace Intel8080 return AdjustParity(input, value); } + private void AdjustSZP(byte value) => this.F = AdjustSZP(this.F, value); + private static byte AdjustAuxiliaryCarryAdd(byte input, byte before, byte value, int calculation) => SetBit(input, StatusBits.AC, CalculateHalfCarryAdd(before, value, calculation)); + private void AdjustAuxiliaryCarryAdd(byte before, byte value, int calculation) => this.F = AdjustAuxiliaryCarryAdd(this.F, before, value, calculation); + private static byte AdjustAuxiliaryCarrySub(byte input, byte before, byte value, int calculation) => ClearBit(input, StatusBits.AC, CalculateHalfCarrySub(before, value, calculation)); + private void AdjustAuxiliaryCarrySub(byte before, byte value, int calculation) => this.F = AdjustAuxiliaryCarrySub(this.F, before, value, calculation); + protected override void DisableInterrupts() => this.interruptEnable = false; protected override void EnableInterrupts() => this.interruptEnable = true; + private Register16 RP(int rp) => rp switch + { + 0 => this.BC, + 1 => this.DE, + 2 => this.HL, + 3 => this.SP, + _ => throw new ArgumentOutOfRangeException(nameof(rp)), + }; + + private Register16 RP2(int rp) => rp switch + { + 0 => this.BC, + 1 => this.DE, + 2 => this.HL, + 3 => this.AF, + _ => throw new ArgumentOutOfRangeException(nameof(rp)), + }; + private ref byte R(int r, AccessLevel access = AccessLevel.ReadOnly) { switch (r) @@ -226,24 +261,6 @@ namespace Intel8080 } } - private Register16 RP(int rp) => rp switch - { - 0 => this.BC, - 1 => this.DE, - 2 => this.HL, - 3 => this.SP, - _ => throw new ArgumentOutOfRangeException(nameof(rp)), - }; - - private Register16 RP2(int rp) => rp switch - { - 0 => this.BC, - 1 => this.DE, - 2 => this.HL, - 3 => this.AF, - _ => throw new ArgumentOutOfRangeException(nameof(rp)), - }; - private void Execute(int x, int y, int z, int p, int q) { var memoryY = y == 6; @@ -403,37 +420,40 @@ namespace Intel8080 this.R(y, this.R(z)); } break; - case 2: // Operate on accumulator and register/memory location - switch (y) - { - case 0: // ADD A,r - this.Add(this.R(z)); - break; - case 1: // ADC A,r - this.ADC(this.R(z)); - break; - case 2: // SUB r - this.SUB(this.R(z)); - break; - case 3: // SBC A,r - this.SBB(this.R(z)); - break; - case 4: // AND r - this.AndR(this.R(z)); - break; - case 5: // XOR r - this.XorR(this.R(z)); - break; - case 6: // OR r - this.OrR(this.R(z)); - break; - case 7: // CP r - this.Compare(this.R(z)); - break; - default: - throw new NotSupportedException("Invalid operation mode"); + case 2: + { // Operate on accumulator and register/memory location + var value = this.R(z); + switch (y) + { + case 0: // ADD A,r + this.A = this.Add(this.A, value); + break; + case 1: // ADC A,r + this.A = this.ADC(this.A, value); + break; + case 2: // SUB r + this.A = this.SUB(this.A, value); + break; + case 3: // SBC A,r + this.A = this.SBC(this.A, value); + break; + case 4: // AND r + this.AndR(value); + break; + case 5: // XOR r + this.XorR(value); + break; + case 6: // OR r + this.OrR(value); + break; + case 7: // CP r + this.Compare(value); + break; + default: + throw new NotSupportedException("Invalid operation mode"); + } + break; } - break; case 3: switch (z) { @@ -528,38 +548,40 @@ namespace Intel8080 } break; - case 6: // Operate on accumulator and immediate operand: alu[y] n - _ = this.FetchByte(); - switch (y) - { - case 0: // ADD A,n - this.Add(this.Bus.Data); - break; - case 1: // ADC A,n - this.ADC(this.Bus.Data); - break; - case 2: // SUB n - this.SUB(this.Bus.Data); - break; - case 3: // SBC A,n - this.SBB(this.Bus.Data); - break; - case 4: // AND n - this.AndR(this.Bus.Data); - break; - case 5: // XOR n - this.XorR(this.Bus.Data); - break; - case 6: // OR n - this.OrR(this.Bus.Data); - break; - case 7: // CP n - this.Compare(this.Bus.Data); - break; - default: - throw new NotSupportedException("Invalid operation mode"); + case 6: + { // Operate on accumulator and immediate operand: alu[y] n + var operand = this.FetchByte(); + switch (y) + { + case 0: // ADD A,n + this.A = this.Add(this.A, operand); + break; + case 1: // ADC A,n + this.A = this.ADC(this.A, operand); + break; + case 2: // SUB n + this.A = this.SUB(this.A, operand); + break; + case 3: // SBC A,n + this.A = this.SBC(this.A, operand); + break; + case 4: // AND n + this.AndR(operand); + break; + case 5: // XOR n + this.XorR(operand); + break; + case 6: // OR n + this.OrR(operand); + break; + case 7: // CP n + this.Compare(operand); + break; + default: + throw new NotSupportedException("Invalid operation mode"); + } + break; } - break; case 7: // Restart: RST y * 8 this.Restart((byte)(y << 3)); break; @@ -575,16 +597,18 @@ namespace Intel8080 private byte Increment(byte operand) { - this.F = AdjustSZP(this.F, ++operand); - this.F = ClearBit(this.F, StatusBits.AC, LowNibble(operand)); - return operand; + var result = operand; ++operand; + AdjustSZP(result); + ClearBit(StatusBits.AC, LowNibble(result)); + return result; } private byte Decrement(byte operand) { - this.F = AdjustSZP(this.F, --operand); - this.F = SetBit(this.F, StatusBits.AC, LowNibble(operand) != (byte)Mask.Four); - return operand; + var result = operand; --operand; + AdjustSZP(result); + SetBit(StatusBits.AC, LowNibble(result) != (byte)Mask.Four); + return result; } protected sealed override bool ConvertCondition(int flag) => flag switch @@ -614,58 +638,58 @@ namespace Intel8080 { var result = this.HL.Word + value.Word; this.HL.Word = (ushort)result; - this.F = SetBit(this.F, StatusBits.CF, result & (int)Bits.Bit16); + SetBit(StatusBits.CF, result & (int)Bits.Bit16); } - private void Add(byte value, int carry = 0) + private byte Add(byte operand, byte value, int carry = 0) { - this.MEMPTR.Word = (ushort)(this.A + value + carry); + this.Intermediate.Word = (ushort)(operand + value + carry); + var result = this.Intermediate.Low; - this.F = AdjustAuxiliaryCarryAdd(this.F, this.A, value, this.MEMPTR.Low); + AdjustAuxiliaryCarryAdd(operand, value, result); - this.A = this.MEMPTR.Low; - - this.F = SetBit(this.F, StatusBits.CF, CarryTest(this.MEMPTR.High)); - this.F = AdjustSZP(this.F, this.A); - } - - private void ADC(byte value) => this.Add(value, this.Carry()); - - private byte Subtract(byte operand, byte value, int carry = 0) - { - this.MEMPTR.Word = (ushort)(operand - value - carry); - - this.F = AdjustAuxiliaryCarrySub(this.F, operand, value, this.MEMPTR.Word); - - var result = this.MEMPTR.Low; - - this.F = SetBit(this.F, StatusBits.CF, CarryTest(this.MEMPTR.High)); - this.F = AdjustSZP(this.F, result); + SetBit(StatusBits.CF, CarryTest(this.Intermediate.High)); + AdjustSZP(result); return result; } - private void SUB(byte value, int carry = 0) => this.A = this.Subtract(this.A, value, carry); + private byte ADC(byte operand, byte value) => this.Add(operand, value, this.Carry()); - private void SBB(byte value) => this.SUB(value, this.Carry()); + private byte Subtract(byte operand, byte value, int carry = 0) + { + this.Intermediate.Word = (ushort)(operand - value - carry); + var result = this.Intermediate.Low; + + AdjustAuxiliaryCarrySub(operand, value, this.Intermediate.Word); + + SetBit(StatusBits.CF, CarryTest(this.Intermediate.High)); + AdjustSZP(result); + + return result; + } + + private byte SUB(byte operand, byte value, int carry = 0) => this.Subtract(operand, value, carry); + + private byte SBC(byte operand, byte value) => this.SUB(operand, value, this.Carry()); private void AndR(byte value) { - this.F = SetBit(this.F, StatusBits.AC, (this.A | value) & (int)Bits.Bit3); - this.F = ClearBit(this.F, StatusBits.CF); - this.F = AdjustSZP(this.F, this.A &= value); + SetBit(StatusBits.AC, (this.A | value) & (int)Bits.Bit3); + ClearBit(StatusBits.CF); + AdjustSZP(this.A &= value); } private void XorR(byte value) { - this.F = ClearBit(this.F, StatusBits.AC | StatusBits.CF); - this.F = AdjustSZP(this.F, this.A ^= value); + ClearBit(StatusBits.AC | StatusBits.CF); + AdjustSZP(this.A ^= value); } private void OrR(byte value) { - this.F = ClearBit(this.F, StatusBits.AC | StatusBits.CF); - this.F = AdjustSZP(this.F, this.A |= value); + ClearBit(StatusBits.AC | StatusBits.CF); + AdjustSZP(this.A |= value); } private void Compare(byte value) => this.Subtract(this.A, value); @@ -673,28 +697,28 @@ namespace Intel8080 private byte RLC(byte operand) { var carry = operand & (byte)Bits.Bit7; - this.F = SetBit(this.F, StatusBits.CF, carry); + SetBit(StatusBits.CF, carry); return (byte)((operand << 1) | (carry >> 7)); } private byte RRC(byte operand) { var carry = operand & (byte)Bits.Bit0; - this.F = SetBit(this.F, StatusBits.CF, carry); + SetBit(StatusBits.CF, carry); return (byte)((operand >> 1) | (carry << 7)); } private byte RL(byte operand) { var carry = this.Carry(); - this.F = SetBit(this.F, StatusBits.CF, operand & (byte)Bits.Bit7); + SetBit(StatusBits.CF, operand & (byte)Bits.Bit7); return (byte)((operand << 1) | carry); } private byte RR(byte operand) { var carry = this.Carry(); - this.F = SetBit(this.F, StatusBits.CF, operand & (byte)Bits.Bit0); + SetBit(StatusBits.CF, operand & (byte)Bits.Bit0); return (byte)((operand >> 1) | (carry << 7)); } @@ -714,15 +738,15 @@ namespace Intel8080 carry = true; } - this.Add(addition); - this.F = SetBit(this.F, StatusBits.CF, carry); + this.A = this.Add(this.A, addition); + SetBit(StatusBits.CF, carry); } private void CMA() => this.A = (byte)~this.A; - private void STC() => this.F = SetBit(this.F, StatusBits.CF); + private void STC() => SetBit(StatusBits.CF); - private void CMC() => this.F = ClearBit(this.F, StatusBits.CF, this.Carry()); + private void CMC() => ClearBit(StatusBits.CF, this.Carry()); private void XHTL(Register16 exchange) { diff --git a/LR35902/LR35902.cs b/LR35902/LR35902.cs index 3d8309e..7771d6b 100644 --- a/LR35902/LR35902.cs +++ b/LR35902/LR35902.cs @@ -324,9 +324,9 @@ namespace LR35902 private static byte AdjustHalfCarrySub(byte input, byte before, byte value, int calculation) => SetBit(input, StatusBits.HC, CalculateHalfCarrySub(before, value, calculation)); - private static byte Res(int n, byte operand) => ClearBit(operand, Bit(n)); + private static byte RES(int n, byte operand) => ClearBit(operand, Bit(n)); - private static byte Set(int n, byte operand) => SetBit(operand, Bit(n)); + private static byte SET(int n, byte operand) => SetBit(operand, Bit(n)); protected override void DisableInterrupts() => this.IME = false; @@ -336,23 +336,28 @@ namespace LR35902 private void Start() => this.Stopped = false; - protected override void MemoryWrite() + private void MemoryUpdate(int ticks) { this.LowerMWR(); - this.LowerWR(); - base.MemoryWrite(); - this.TickMachine(); - this.RaiseWR(); + this.LowerWR(); + base.MemoryWrite(); + this.TickMachine(ticks); + this.RaiseWR(); this.RaiseMWR(); } + protected override void MemoryWrite() + { + this.MemoryUpdate(1); + } + protected override byte MemoryRead() { this.LowerMWR(); - this.LowerRD(); - _ = base.MemoryRead(); - this.TickMachine(); - this.RaiseRD(); + this.LowerRD(); + _ = base.MemoryRead(); + this.TickMachine(); + this.RaiseRD(); this.RaiseMWR(); return this.Bus.Data; } @@ -396,52 +401,53 @@ namespace LR35902 this.TickMachine(); } - private byte R(int r) => r switch - { - 0 => this.B, - 1 => this.C, - 2 => this.D, - 3 => this.E, - 4 => this.H, - 5 => this.L, - 6 => this.MemoryRead(this.HL), - 7 => this.A, - _ => throw new ArgumentOutOfRangeException(nameof(r)), - }; - - private void R(int r, byte value) + private ref byte R(int r, AccessLevel access = AccessLevel.ReadOnly) { switch (r) { case 0: - this.B = value; - break; + return ref this.B; case 1: - this.C = value; - break; + return ref this.C; case 2: - this.D = value; - break; + return ref this.D; case 3: - this.E = value; - break; + return ref this.E; case 4: - this.H = value; - break; + return ref this.H; case 5: - this.L = value; - break; + return ref this.L; case 6: - this.MemoryWrite(this.HL, value); - break; + this.Bus.Address.Assign(this.HL); + switch (access) + { + case AccessLevel.ReadOnly: + this.MemoryRead(); + break; + case AccessLevel.WriteOnly: + break; + default: + throw new NotSupportedException("Invalid access level"); + } + + // Will need a post-MemoryWrite + return ref this.Bus.Data; case 7: - this.A = value; - break; + return ref this.A; default: throw new ArgumentOutOfRangeException(nameof(r)); } } + private void R(int r, byte value, int ticks = 1) + { + this.R(r, AccessLevel.WriteOnly) = value; + if (r == 6) + { + this.MemoryUpdate(ticks); + } + } + private Register16 RP(int rp) => rp switch { 0 => this.BC, @@ -462,11 +468,12 @@ namespace LR35902 private void ExecuteCB(int x, int y, int z) { + var operand = this.R(z); + var update = x != 1; // BIT does not update switch (x) { case 0: // rot[y] r[z] { - var operand = this.R(z); operand = y switch { 0 => this.RLC(operand), @@ -479,30 +486,36 @@ namespace LR35902 7 => this.SRL(operand), _ => throw new InvalidOperationException("Unreachable code block reached"), }; - this.R(z, operand); this.AdjustZero(operand); } break; case 1: // BIT y, r[z] - this.Bit(y, this.R(z)); + this.Bit(y, operand); break; case 2: // RES y, r[z] - this.R(z, Res(y, this.R(z))); + operand = RES(y, operand); break; case 3: // SET y, r[z] - this.R(z, Set(y, this.R(z))); + operand = SET(y, operand); break; default: throw new InvalidOperationException("Unreachable code block reached"); } + + if (update) + { + this.R(z, operand); + } } private void ExecuteOther(int x, int y, int z, int p, int q) { + var memoryY = y == 6; + var memoryZ = z == 6; switch (x) { case 0: @@ -544,7 +557,8 @@ namespace LR35902 break; case 1: // ADD HL,rp - this.Add(this.HL, this.RP(p)); + this.Add(this.RP(p)); + this.TickMachine(); break; default: @@ -616,14 +630,18 @@ namespace LR35902 break; case 3: // 16-bit INC/DEC - _ = q switch + switch (q) { - // INC rp - 0 => this.RP(p).Increment(), - // DEC rp - 1 => this.RP(p).Decrement(), - _ => throw new InvalidOperationException("Invalid operation mode"), - }; + case 0: // INC rp + this.RP(p).Increment(); + break; + + case 1: // DEC rp + this.RP(p).Decrement(); + break; + default: + throw new InvalidOperationException("Invalid operation mode"); + } this.TickMachine(); break; @@ -678,48 +696,51 @@ namespace LR35902 break; case 1: // 8-bit loading - if (z == 6 && y == 6) + if (!(memoryZ && memoryY)) + { + this.R(y, this.R(z)); + } + else { this.LowerHALT(); // Exception (replaces LD (HL), (HL)) this.TickMachine(2); } - else - { - this.R(y, this.R(z)); - } break; - case 2: // Operate on accumulator and register/memory location - switch (y) - { - case 0: // ADD A,r - this.A = this.Add(this.A, this.R(z)); - break; - case 1: // ADC A,r - this.A = this.ADC(this.A, this.R(z)); - break; - case 2: // SUB r - this.A = this.Subtract(this.A, this.R(z)); - break; - case 3: // SBC A,r - this.A = this.SBC(this.A, this.R(z)); - break; - case 4: // AND r - this.AndR(this.R(z)); - break; - case 5: // XOR r - this.XorR(this.R(z)); - break; - case 6: // OR r - this.OrR(this.R(z)); - break; - case 7: // CP r - this.Compare(this.R(z)); - break; - default: - throw new InvalidOperationException("Invalid operation mode"); + case 2: + { // Operate on accumulator and register/memory location + var value = this.R(z); + switch (y) + { + case 0: // ADD A,r + this.A = this.Add(this.A, value); + break; + case 1: // ADC A,r + this.A = this.ADC(this.A, value); + break; + case 2: // SUB r + this.A = this.Subtract(this.A, value); + break; + case 3: // SBC A,r + this.A = this.SBC(this.A, value); + break; + case 4: // AND r + this.AndR(value); + break; + case 5: // XOR r + this.XorR(value); + break; + case 6: // OR r + this.OrR(value); + break; + case 7: // CP r + this.Compare(value); + break; + default: + throw new InvalidOperationException("Invalid operation mode"); + } + break; } - break; case 3: switch (z) { @@ -886,38 +907,40 @@ namespace LR35902 break; - case 6: // Operate on accumulator and immediate operand: alu[y] n - _ = this.FetchByte(); - switch (y) - { - case 0: // ADD A,n - this.A = this.Add(this.A, this.Bus.Data); - break; - case 1: // ADC A,n - this.A = this.ADC(this.A, this.Bus.Data); - break; - case 2: // SUB n - this.A = this.Subtract(this.A, this.Bus.Data); - break; - case 3: // SBC A,n - this.A = this.SBC(this.A, this.Bus.Data); - break; - case 4: // AND n - this.AndR(this.Bus.Data); - break; - case 5: // XOR n - this.XorR(this.Bus.Data); - break; - case 6: // OR n - this.OrR(this.Bus.Data); - break; - case 7: // CP n - this.Compare(this.Bus.Data); - break; - default: - throw new InvalidOperationException("Invalid operation mode"); + case 6: + { // Operate on accumulator and immediate operand: alu[y] n + var operand = this.FetchByte(); + switch (y) + { + case 0: // ADD A,n + this.A = this.Add(this.A, operand); + break; + case 1: // ADC A,n + this.A = this.ADC(this.A, operand); + break; + case 2: // SUB n + this.A = this.Subtract(this.A, operand); + break; + case 3: // SBC A,n + this.A = this.SBC(this.A, operand); + break; + case 4: // AND n + this.AndR(operand); + break; + case 5: // XOR n + this.XorR(operand); + break; + case 6: // OR n + this.OrR(operand); + break; + case 7: // CP n + this.Compare(operand); + break; + default: + throw new InvalidOperationException("Invalid operation mode"); + } + break; } - break; case 7: // Restart: RST y * 8 this.Restart((byte)(y << 3)); @@ -936,17 +959,19 @@ namespace LR35902 private byte Increment(byte operand) { this.ClearBit(StatusBits.NF); - this.AdjustZero(++operand); - this.ClearBit(StatusBits.HC, LowNibble(operand)); - return operand; + var result = operand; ++result; + this.AdjustZero(result); + this.ClearBit(StatusBits.HC, LowNibble(result)); + return result; } private byte Decrement(byte operand) { this.SetBit(StatusBits.NF); this.ClearBit(StatusBits.HC, LowNibble(operand)); - this.AdjustZero(--operand); - return operand; + var result = operand; --result; + this.AdjustZero(result); + return result; } protected sealed override bool ConvertCondition(int flag) => flag switch @@ -958,49 +983,42 @@ namespace LR35902 _ => throw new ArgumentOutOfRangeException(nameof(flag)), }; - private void Add(Register16 operand, Register16 value) + private void Add(Register16 value) { - this.TickMachine(); - - this.MEMPTR.Assign(operand); - - var result = this.MEMPTR.Word + value.Word; - - operand.Word = (ushort)result; - + this.Intermediate.Assign(this.HL); + var result = this.HL.Word + value.Word; + this.HL.Word = (ushort)result; this.ClearBit(StatusBits.NF); this.SetBit(StatusBits.CF, result & (int)Bits.Bit16); - this.AdjustHalfCarryAdd(this.MEMPTR.High, value.High, operand.High); + this.AdjustHalfCarryAdd(this.Intermediate.High, value.High, this.HL.High); } private byte Add(byte operand, byte value, int carry = 0) { - this.MEMPTR.Word = (ushort)(operand + value + carry); + this.Intermediate.Word = (ushort)(operand + value + carry); + var result = this.Intermediate.Low; - this.AdjustHalfCarryAdd(operand, value, this.MEMPTR.Low); - - operand = this.MEMPTR.Low; + this.AdjustHalfCarryAdd(operand, value, result); this.ClearBit(StatusBits.NF); - this.SetBit(StatusBits.CF, this.MEMPTR.Word & (ushort)Bits.Bit8); - this.AdjustZero(operand); + this.SetBit(StatusBits.CF, this.Intermediate.High & (byte)Bits.Bit0); + this.AdjustZero(result); - return operand; + return result; } private byte ADC(byte operand, byte value) => this.Add(operand, value, this.Carry() >> 4); private byte Subtract(byte operand, byte value, int carry = 0) { - this.MEMPTR.Word = (ushort)(operand - value - carry); + this.Intermediate.Word = (ushort)(operand - value - carry); + var result = this.Intermediate.Low; - this.AdjustHalfCarrySub(operand, value, this.MEMPTR.Low); - - var result = operand = this.MEMPTR.Low; + this.AdjustHalfCarrySub(operand, value, result); this.SetBit(StatusBits.NF); - this.SetBit(StatusBits.CF, this.MEMPTR.High & (byte)Bits.Bit0); - this.AdjustZero(operand); + this.SetBit(StatusBits.CF, this.Intermediate.High & (byte)Bits.Bit0); + this.AdjustZero(result); return result; } diff --git a/Z80/Z80.cs b/Z80/Z80.cs index ad693b4..8335a3b 100644 --- a/Z80/Z80.cs +++ b/Z80/Z80.cs @@ -933,7 +933,7 @@ namespace Z80 switch (z) { case 0: // Input from port with 16-bit address - _ = this.ReadPort(this.BC); + this.ReadPort(this.BC); this.MEMPTR.Increment(); if (y != 6) { @@ -1480,7 +1480,8 @@ namespace Z80 this.WritePort(this.FetchByte()); break; case 3: // IN A,(n) - this.A = this.ReadPort(this.FetchByte()); + this.ReadPort(this.FetchByte()); + this.A = this.Bus.Data; break; case 4: // EX (SP),HL this.XHTL(this.HL2()); @@ -2138,7 +2139,7 @@ namespace Z80 private void BlockIn() { this.Tick(); - _ = this.ReadPort(this.BC); + this.ReadPort(this.BC); this.Bus.Address.Assign(this.HL); this.MemoryUpdate(1); this.AdjustSZXY(--this.B); @@ -2293,6 +2294,12 @@ namespace Z80 #region Input/output port control + private void WritePort(Register16 port, byte data) + { + this.Bus.Data = data; + this.WritePort(port); + } + private void WritePort(byte port) { this.Bus.Address.Assign(port, this.Bus.Data = this.A); @@ -2300,12 +2307,6 @@ namespace Z80 ++this.MEMPTR.Low; } - private void WritePort(Register16 port, byte data) - { - this.Bus.Data = data; - this.WritePort(port); - } - private void WritePort(Register16 port) { this.Bus.Address.Assign(port); @@ -2315,8 +2316,7 @@ namespace Z80 private void WritePort() { this.MEMPTR.Assign(this.Bus.Address); - this.Tick(); - this.Tick(); + this.Tick(2); this.LowerIORQ(); this.LowerWR(); this.Tick(); @@ -2326,21 +2326,20 @@ namespace Z80 this.Tick(); } - private byte ReadPort(byte port) - { - this.Bus.Address.Assign(port, this.Bus.Data = this.A); - _ = this.ReadPort(); - this.MEMPTR.Increment(); - return this.Bus.Data; - } - - private byte ReadPort(Register16 port) + private void ReadPort(Register16 port) { this.Bus.Address.Assign(port); - return this.ReadPort(); + this.ReadPort(); } - private byte ReadPort() + private void ReadPort(byte port) + { + this.Bus.Address.Assign(port, this.Bus.Data = this.A); + this.ReadPort(); + this.MEMPTR.Increment(); + } + + private void ReadPort() { this.MEMPTR.Assign(this.Bus.Address); this.Tick(2); @@ -2351,7 +2350,6 @@ namespace Z80 this.RaiseRD(); this.RaiseIORQ(); this.Tick(); - return this.Bus.Data; } #endregion