Lots of stylecop encouraged changes.

Signed-off-by: Adrian Conlon <Adrian.conlon@gmail.com>
This commit is contained in:
Adrian Conlon 2019-02-19 00:56:16 +00:00
parent 23489b7127
commit 5714798756
4 changed files with 171 additions and 67 deletions

View File

@ -13,7 +13,7 @@ namespace UnitTestEightBit
[TestMethod] [TestMethod]
public void TestLowByte() public void TestLowByte()
{ {
ushort input = 0xf00f; const ushort input = 0xf00f;
byte low = Chip.LowByte(input); byte low = Chip.LowByte(input);
Assert.AreEqual(0xf, low); Assert.AreEqual(0xf, low);
} }
@ -21,7 +21,7 @@ namespace UnitTestEightBit
[TestMethod] [TestMethod]
public void TestHighByte() public void TestHighByte()
{ {
ushort input = 0xf00f; const ushort input = 0xf00f;
byte high = Chip.HighByte(input); byte high = Chip.HighByte(input);
Assert.AreEqual(0xf0, high); Assert.AreEqual(0xf0, high);
} }
@ -109,7 +109,7 @@ namespace UnitTestEightBit
[TestMethod] [TestMethod]
public void TestLowerPart() public void TestLowerPart()
{ {
ushort input = 0xf00f; const ushort input = 0xf00f;
ushort lower = Chip.LowerPart(input); ushort lower = Chip.LowerPart(input);
Assert.AreEqual(0xf, lower); Assert.AreEqual(0xf, lower);
} }
@ -117,7 +117,7 @@ namespace UnitTestEightBit
[TestMethod] [TestMethod]
public void TestHigherPart() public void TestHigherPart()
{ {
ushort input = 0xf00f; const ushort input = 0xf00f;
ushort higher = Chip.HigherPart(input); ushort higher = Chip.HigherPart(input);
Assert.AreEqual(0xf000, higher); Assert.AreEqual(0xf000, higher);
} }
@ -125,7 +125,7 @@ namespace UnitTestEightBit
[TestMethod] [TestMethod]
public void TestDemoteByte() public void TestDemoteByte()
{ {
ushort input = 0xf00f; const ushort input = 0xf00f;
byte demoted = Chip.DemoteByte(input); byte demoted = Chip.DemoteByte(input);
Assert.AreEqual(0xf0, demoted); Assert.AreEqual(0xf0, demoted);
} }
@ -133,7 +133,7 @@ namespace UnitTestEightBit
[TestMethod] [TestMethod]
public void TestPromoteByte() public void TestPromoteByte()
{ {
byte input = 0xf0; const byte input = 0xf0;
ushort promoted = Chip.PromoteByte(input); ushort promoted = Chip.PromoteByte(input);
Assert.AreEqual(0xf000, promoted); Assert.AreEqual(0xf000, promoted);
} }
@ -141,7 +141,7 @@ namespace UnitTestEightBit
[TestMethod] [TestMethod]
public void TestLowNibble() public void TestLowNibble()
{ {
byte input = 0xab; const byte input = 0xab;
int nibble = Chip.LowNibble(input); int nibble = Chip.LowNibble(input);
Assert.AreEqual(0xb, nibble); Assert.AreEqual(0xb, nibble);
} }
@ -149,7 +149,7 @@ namespace UnitTestEightBit
[TestMethod] [TestMethod]
public void TestHighNibble() public void TestHighNibble()
{ {
byte input = 0xab; const byte input = 0xab;
int nibble = Chip.HighNibble(input); int nibble = Chip.HighNibble(input);
Assert.AreEqual(0xa, nibble); Assert.AreEqual(0xa, nibble);
} }
@ -157,7 +157,7 @@ namespace UnitTestEightBit
[TestMethod] [TestMethod]
public void TestDemoteNibble() public void TestDemoteNibble()
{ {
byte input = 0xab; const byte input = 0xab;
int nibble = Chip.DemoteNibble(input); int nibble = Chip.DemoteNibble(input);
Assert.AreEqual(0xa, nibble); Assert.AreEqual(0xa, nibble);
} }
@ -165,7 +165,7 @@ namespace UnitTestEightBit
[TestMethod] [TestMethod]
public void TestPromoteNibble() public void TestPromoteNibble()
{ {
byte input = 0xab; const byte input = 0xab;
int nibble = Chip.PromoteNibble(input); int nibble = Chip.PromoteNibble(input);
Assert.AreEqual(0xb0, nibble); Assert.AreEqual(0xb0, nibble);
} }
@ -173,7 +173,7 @@ namespace UnitTestEightBit
[TestMethod] [TestMethod]
public void TestHigherNibble() public void TestHigherNibble()
{ {
byte input = 0xab; const byte input = 0xab;
int nibble = Chip.HigherNibble(input); int nibble = Chip.HigherNibble(input);
Assert.AreEqual(0xa0, nibble); Assert.AreEqual(0xa0, nibble);
} }
@ -181,7 +181,7 @@ namespace UnitTestEightBit
[TestMethod] [TestMethod]
public void TestLowerNibble() public void TestLowerNibble()
{ {
byte input = 0xab; const byte input = 0xab;
int nibble = Chip.LowerNibble(input); int nibble = Chip.LowerNibble(input);
Assert.AreEqual(0xb, nibble); Assert.AreEqual(0xb, nibble);
} }

View File

@ -21,6 +21,12 @@
return FromByte(input); return FromByte(input);
} }
public static RefreshRegister operator ++(RefreshRegister value) => Increment(value);
public static bool operator ==(RefreshRegister left, RefreshRegister right) => left.Equals(right);
public static bool operator !=(RefreshRegister left, RefreshRegister right) => !(left == right);
public static byte ToByte(RefreshRegister input) public static byte ToByte(RefreshRegister input)
{ {
return (byte)((input.high << 7) | input.variable); return (byte)((input.high << 7) | input.variable);
@ -31,12 +37,6 @@
return new RefreshRegister(input); return new RefreshRegister(input);
} }
public static RefreshRegister operator ++(RefreshRegister value) => Increment(value);
public static bool operator ==(RefreshRegister left, RefreshRegister right) => left.Equals(right);
public static bool operator !=(RefreshRegister left, RefreshRegister right) => !(left == right);
public static RefreshRegister Increment(RefreshRegister value) public static RefreshRegister Increment(RefreshRegister value)
{ {
++value.variable; ++value.variable;

13
Z80/RegisterIndex.cs Normal file
View File

@ -0,0 +1,13 @@
// <copyright file="RegisterIndex.cs" company="Adrian Conlon">
// Copyright (c) Adrian Conlon. All rights reserved.
// </copyright>
namespace EightBit
{
public enum RegisterIndex
{
IndexBC,
IndexDE,
IndexHL,
}
}

View File

@ -8,10 +8,11 @@ namespace EightBit
public class Z80 : IntelProcessor public class Z80 : IntelProcessor
{ {
public enum RegisterIndex { IndexBC, IndexDE, IndexHL };
private readonly InputOutput ports; private readonly InputOutput ports;
private readonly Register16[] accumulatorFlags = new Register16[2];
private readonly Register16[,] registers = new Register16[2, 3];
private RefreshRegister refresh = new RefreshRegister(0x7f); private RefreshRegister refresh = new RefreshRegister(0x7f);
private bool prefixCB = false; private bool prefixCB = false;
@ -22,10 +23,8 @@ namespace EightBit
private PinLevel nmiLine = PinLevel.Low; private PinLevel nmiLine = PinLevel.Low;
private PinLevel m1Line = PinLevel.Low; private PinLevel m1Line = PinLevel.Low;
private readonly Register16[] accumulatorFlags = new Register16[2];
private int accumulatorFlagsSet = 0; private int accumulatorFlagsSet = 0;
private readonly Register16[,] registers = new Register16[2,3];
private int registerSet = 0; private int registerSet = 0;
private Register16 ix = new Register16(0xffff); private Register16 ix = new Register16(0xffff);
@ -73,7 +72,7 @@ namespace EightBit
get get
{ {
var returned = (this.prefixDD ? this.IX() : this.IY()).Word + this.displacement; var returned = (this.prefixDD ? this.IX() : this.IY()).Word + this.displacement;
return MEMPTR().Word = (ushort)returned; return this.MEMPTR().Word = (ushort)returned;
} }
} }
@ -177,9 +176,13 @@ namespace EightBit
if (prefixed) if (prefixed)
{ {
if (this.prefixCB) 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
{ {
@ -218,6 +221,7 @@ namespace EightBit
this.Execute(this.FetchByte()); this.Execute(this.FetchByte());
} }
} }
this.OnExecutedInstruction(); this.OnExecutedInstruction();
return this.Cycles; return this.Cycles;
} }
@ -258,7 +262,7 @@ namespace EightBit
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(this.Bus.Data);
break; break;
case 1: case 1:
@ -266,7 +270,7 @@ namespace EightBit
this.Tick(13); this.Tick(13);
break; break;
case 2: case 2:
this.Call(this.MEMPTR() = new Register16(this.Bus.Data, IV)); this.Call(this.MEMPTR() = new Register16(this.Bus.Data, this.IV));
this.Tick(19); this.Tick(19);
break; break;
default: default:
@ -310,7 +314,7 @@ namespace EightBit
private static byte AdjustSZP(byte input, byte value) private static byte AdjustSZP(byte input, byte value)
{ {
AdjustSZ(input, value); input = AdjustSZ(input, value);
return AdjustParity(input, value); return AdjustParity(input, value);
} }
@ -364,6 +368,16 @@ namespace EightBit
return AdjustOverflowSub(input, before & (byte)StatusBits.SF, value & (byte)StatusBits.SF, calculation & (byte)StatusBits.SF); return AdjustOverflowSub(input, before & (byte)StatusBits.SF, value & (byte)StatusBits.SF, calculation & (byte)StatusBits.SF);
} }
private static byte RES(int n, byte operand)
{
return (byte)(operand & ~(1 << n));
}
private static byte SET(int n, byte operand)
{
return (byte)(operand | (1 << n));
}
private void DisableInterrupts() => this.IFF1 = this.IFF2 = false; private void DisableInterrupts() => this.IFF1 = this.IFF2 = false;
private void EnableInterrupts() => this.IFF1 = this.IFF2 = true; private void EnableInterrupts() => this.IFF1 = this.IFF2 = true;
@ -502,7 +516,7 @@ namespace EightBit
this.Bus.Write(this.HL(), value); this.Bus.Write(this.HL(), value);
break; break;
case 7: case 7:
A() = value; this.A() = value;
break; break;
default: default:
throw new ArgumentOutOfRangeException(nameof(r)); throw new ArgumentOutOfRangeException(nameof(r));
@ -515,11 +529,11 @@ namespace EightBit
var memoryZ = z == 6; var memoryZ = z == 6;
var indirect = (!this.displaced && memoryZ) || this.displaced; var indirect = (!this.displaced && memoryZ) || this.displaced;
var direct = !indirect; var direct = !indirect;
var operand = !this.displaced ? R(z) : Bus.Read(this.DisplacedAddress); var operand = !this.displaced ? this.R(z) : this.Bus.Read(this.DisplacedAddress);
var update = x != 1; // BIT does not update var update = x != 1; // BIT does not update
switch (x) switch (x)
{ {
case 0: // rot[y] r[z] case 0: // rot[y] r[z]
switch (y) switch (y)
{ {
case 0: case 0:
@ -549,6 +563,7 @@ namespace EightBit
default: default:
throw new NotSupportedException("Invalid operation mode"); throw new NotSupportedException("Invalid operation mode");
} }
this.F() = AdjustSZP(this.F(), operand); this.F() = AdjustSZP(this.F(), operand);
this.Tick(8); this.Tick(8);
break; break;
@ -564,6 +579,7 @@ namespace EightBit
this.F() = AdjustXY(this.F(), this.MEMPTR().High); this.F() = AdjustXY(this.F(), this.MEMPTR().High);
this.Tick(4); this.Tick(4);
} }
break; break;
case 2: // RES y, r[z] case 2: // RES y, r[z]
this.Tick(8); this.Tick(8);
@ -576,6 +592,7 @@ namespace EightBit
default: default:
throw new NotSupportedException("Invalid operation mode"); throw new NotSupportedException("Invalid operation mode");
} }
if (update) if (update)
{ {
if (!this.displaced) if (!this.displaced)
@ -612,8 +629,11 @@ namespace EightBit
this.MEMPTR() = this.Bus.Address() = this.BC(); this.MEMPTR() = this.Bus.Address() = this.BC();
this.MEMPTR()++; this.MEMPTR()++;
this.ReadPort(); this.ReadPort();
if (y != 6) // IN r[y],(C) if (y != 6)
this.R(y, this.Bus.Data); {
this.R(y, this.Bus.Data); // IN r[y],(C)
}
this.F() = AdjustSZPXY(this.F(), this.Bus.Data); this.F() = AdjustSZPXY(this.F(), this.Bus.Data);
this.F() = ClearFlag(this.F(), StatusBits.NF | StatusBits.HC); this.F() = ClearFlag(this.F(), StatusBits.NF | StatusBits.HC);
this.Tick(12); this.Tick(12);
@ -621,10 +641,15 @@ namespace EightBit
case 1: // Output to port with 16-bit address case 1: // Output to port with 16-bit address
this.MEMPTR() = this.Bus.Address() = this.BC(); this.MEMPTR() = this.Bus.Address() = this.BC();
this.MEMPTR()++; this.MEMPTR()++;
if (y != 6) // OUT (C),r[y] if (y != 6)
this.Bus.Data = R(y); {
else // OUT (C),0 this.Bus.Data = this.R(y); // OUT (C),r[y]
this.Bus.Data = 0; }
else
{
this.Bus.Data = 0; // OUT (C),0
}
this.WritePort(); this.WritePort();
this.Tick(12); this.Tick(12);
break; break;
@ -640,6 +665,7 @@ namespace EightBit
default: default:
throw new NotSupportedException("Invalid operation mode"); throw new NotSupportedException("Invalid operation mode");
} }
this.Tick(15); this.Tick(15);
break; break;
case 3: // Retrieve/store register pair from/to immediate address case 3: // Retrieve/store register pair from/to immediate address
@ -655,6 +681,7 @@ namespace EightBit
default: default:
throw new NotSupportedException("Invalid operation mode"); throw new NotSupportedException("Invalid operation mode");
} }
this.Tick(20); this.Tick(20);
break; break;
case 4: // Negate accumulator case 4: // Negate accumulator
@ -671,6 +698,7 @@ namespace EightBit
this.RetN(); // RETN this.RetN(); // RETN
break; break;
} }
this.Tick(14); this.Tick(14);
break; break;
case 6: // Set interrupt mode case 6: // Set interrupt mode
@ -693,6 +721,7 @@ namespace EightBit
default: default:
throw new NotSupportedException("Invalid operation mode"); throw new NotSupportedException("Invalid operation mode");
} }
this.Tick(8); this.Tick(8);
break; break;
case 7: // Assorted ops case 7: // Assorted ops
@ -709,13 +738,13 @@ namespace EightBit
case 2: // LD A,I case 2: // LD A,I
this.F() = AdjustSZXY(this.F(), this.A() = this.IV); this.F() = AdjustSZXY(this.F(), this.A() = this.IV);
this.F() = ClearFlag(this.F(), StatusBits.NF | StatusBits.HC); this.F() = ClearFlag(this.F(), StatusBits.NF | StatusBits.HC);
this.F() = SetFlag(this.F(), StatusBits.PF, IFF2); this.F() = SetFlag(this.F(), StatusBits.PF, this.IFF2);
this.Tick(9); this.Tick(9);
break; break;
case 3: // LD A,R case 3: // LD A,R
this.F() = AdjustSZXY(this.F(), this.A() = REFRESH()); this.F() = AdjustSZXY(this.F(), this.A() = this.REFRESH());
this.F() = ClearFlag(this.F(), StatusBits.NF | StatusBits.HC); this.F() = ClearFlag(this.F(), StatusBits.NF | StatusBits.HC);
this.F() = SetFlag(this.F(), StatusBits.PF, IFF2); this.F() = SetFlag(this.F(), StatusBits.PF, this.IFF2);
this.Tick(9); this.Tick(9);
break; break;
case 4: // RRD case 4: // RRD
@ -733,10 +762,12 @@ namespace EightBit
default: default:
throw new NotSupportedException("Invalid operation mode"); throw new NotSupportedException("Invalid operation mode");
} }
break; break;
default: default:
throw new NotSupportedException("Invalid operation mode"); throw new NotSupportedException("Invalid operation mode");
} }
break; break;
case 2: case 2:
switch (z) switch (z)
@ -757,6 +788,7 @@ namespace EightBit
--this.PC(); --this.PC();
this.Tick(5); this.Tick(5);
} }
break; break;
case 7: // LDDR case 7: // LDDR
if (this.LDDR()) if (this.LDDR())
@ -765,8 +797,10 @@ namespace EightBit
--this.PC(); --this.PC();
this.Tick(5); this.Tick(5);
} }
break; break;
} }
break; break;
case 1: // CP case 1: // CP
switch (y) switch (y)
@ -784,6 +818,7 @@ namespace EightBit
--this.PC(); --this.PC();
this.Tick(5); this.Tick(5);
} }
break; break;
case 7: // CPDR case 7: // CPDR
if (this.CPDR()) if (this.CPDR())
@ -796,8 +831,10 @@ namespace EightBit
{ {
this.MEMPTR().Word = (ushort)(this.PC().Word - 2); this.MEMPTR().Word = (ushort)(this.PC().Word - 2);
} }
break; break;
} }
break; break;
case 2: // IN case 2: // IN
switch (y) switch (y)
@ -814,6 +851,7 @@ namespace EightBit
this.PC().Word -= 2; this.PC().Word -= 2;
this.Tick(5); this.Tick(5);
} }
break; break;
case 7: // INDR case 7: // INDR
if (this.INDR()) if (this.INDR())
@ -821,8 +859,10 @@ namespace EightBit
this.PC().Word -= 2; this.PC().Word -= 2;
this.Tick(5); this.Tick(5);
} }
break; break;
} }
break; break;
case 3: // OUT case 3: // OUT
switch (y) switch (y)
@ -839,6 +879,7 @@ namespace EightBit
this.PC().Word -= 2; this.PC().Word -= 2;
this.Tick(5); this.Tick(5);
} }
break; break;
case 7: // OTDR case 7: // OTDR
if (this.OTDR()) if (this.OTDR())
@ -846,10 +887,13 @@ namespace EightBit
this.PC().Word -= 2; this.PC().Word -= 2;
this.Tick(5); this.Tick(5);
} }
break; break;
} }
break; break;
} }
this.Tick(16); this.Tick(16);
break; break;
} }
@ -876,7 +920,10 @@ namespace EightBit
break; break;
case 2: // DJNZ d case 2: // DJNZ d
if (this.JumpRelativeConditional(--this.B() != 0)) if (this.JumpRelativeConditional(--this.B() != 0))
{
this.Tick(5); this.Tick(5);
}
this.Tick(8); this.Tick(8);
break; break;
case 3: // JR d case 3: // JR d
@ -888,12 +935,16 @@ namespace EightBit
case 6: case 6:
case 7: case 7:
if (this.JumpRelativeConditionalFlag(y - 4)) if (this.JumpRelativeConditionalFlag(y - 4))
{
this.Tick(5); this.Tick(5);
}
this.Tick(5); this.Tick(5);
break; break;
default: default:
throw new NotSupportedException("Invalid operation mode"); throw new NotSupportedException("Invalid operation mode");
} }
break; break;
case 1: // 16-bit load immediate/add case 1: // 16-bit load immediate/add
switch (q) switch (q)
@ -909,6 +960,7 @@ namespace EightBit
default: default:
throw new NotSupportedException("Invalid operation mode"); throw new NotSupportedException("Invalid operation mode");
} }
break; break;
case 2: // Indirect loading case 2: // Indirect loading
switch (q) switch (q)
@ -945,6 +997,7 @@ namespace EightBit
default: default:
throw new NotSupportedException("Invalid operation mode"); throw new NotSupportedException("Invalid operation mode");
} }
break; break;
case 1: case 1:
switch (p) switch (p)
@ -975,10 +1028,12 @@ namespace EightBit
default: default:
throw new NotSupportedException("Invalid operation mode"); throw new NotSupportedException("Invalid operation mode");
} }
break; break;
default: default:
throw new NotSupportedException("Invalid operation mode"); throw new NotSupportedException("Invalid operation mode");
} }
break; break;
case 3: // 16-bit INC/DEC case 3: // 16-bit INC/DEC
switch (q) switch (q)
@ -992,11 +1047,15 @@ namespace EightBit
default: default:
throw new NotSupportedException("Invalid operation mode"); throw new NotSupportedException("Invalid operation mode");
} }
this.Tick(6); this.Tick(6);
break; break;
case 4: // 8-bit INC case 4: // 8-bit INC
if (this.displaced && memoryY) if (this.displaced && memoryY)
{
this.FetchDisplacement(); this.FetchDisplacement();
}
this.R(y, this.Increment(this.R(y))); this.R(y, this.Increment(this.R(y)));
this.Tick(4); this.Tick(4);
break; break;
@ -1005,8 +1064,11 @@ namespace EightBit
{ {
this.Tick(7); this.Tick(7);
if (this.displaced) if (this.displaced)
{
this.FetchDisplacement(); this.FetchDisplacement();
}
} }
this.R(y, this.Decrement(this.R(y))); this.R(y, this.Decrement(this.R(y)));
this.Tick(4); this.Tick(4);
break; break;
@ -1015,8 +1077,11 @@ namespace EightBit
{ {
this.Tick(3); this.Tick(3);
if (this.displaced) if (this.displaced)
{
this.FetchDisplacement(); this.FetchDisplacement();
}
} }
this.R(y, this.FetchByte()); // LD r,n this.R(y, this.FetchByte()); // LD r,n
this.Tick(7); this.Tick(7);
break; break;
@ -1050,11 +1115,13 @@ namespace EightBit
default: default:
throw new NotSupportedException("Invalid operation mode"); throw new NotSupportedException("Invalid operation mode");
} }
this.Tick(4); this.Tick(4);
break; break;
default: default:
throw new NotSupportedException("Invalid operation mode"); throw new NotSupportedException("Invalid operation mode");
} }
break; break;
case 1: // 8-bit loading case 1: // 8-bit loading
if (!(memoryZ && memoryY)) if (!(memoryZ && memoryY))
@ -1063,7 +1130,10 @@ namespace EightBit
if (this.displaced) if (this.displaced)
{ {
if (memoryZ || memoryY) if (memoryZ || memoryY)
{
this.FetchDisplacement(); this.FetchDisplacement();
}
if (memoryZ) if (memoryZ)
{ {
switch (y) switch (y)
@ -1078,6 +1148,7 @@ namespace EightBit
break; break;
} }
} }
if (memoryY) if (memoryY)
{ {
switch (z) switch (z)
@ -1093,15 +1164,23 @@ namespace EightBit
} }
} }
} }
if (normal) if (normal)
{
this.R(y, this.R(z)); this.R(y, this.R(z));
if (memoryY || memoryZ) // M operations }
// M operations
if (memoryY || memoryZ)
{
this.Tick(3); this.Tick(3);
}
} }
else else
{ // Exception (replaces LD (HL), (HL)) {
this.Halt(); this.Halt(); // Exception (replaces LD (HL), (HL))
} }
this.Tick(4); this.Tick(4);
break; break;
case 2: case 2:
@ -1110,9 +1189,12 @@ namespace EightBit
{ {
this.Tick(3); this.Tick(3);
if (this.displaced) if (this.displaced)
{
this.FetchDisplacement(); this.FetchDisplacement();
}
} }
var value = R(z);
var value = this.R(z);
switch (y) switch (y)
{ {
case 0: // ADD A,r case 0: // ADD A,r
@ -1142,15 +1224,20 @@ namespace EightBit
default: default:
throw new NotSupportedException("Invalid operation mode"); throw new NotSupportedException("Invalid operation mode");
} }
this.Tick(4); this.Tick(4);
break; break;
} }
case 3: case 3:
switch (z) switch (z)
{ {
case 0: // Conditional return case 0: // Conditional return
if (this.ReturnConditionalFlag(y)) if (this.ReturnConditionalFlag(y))
{
this.Tick(6); this.Tick(6);
}
this.Tick(5); this.Tick(5);
break; break;
case 1: // POP & various ops case 1: // POP & various ops
@ -1182,10 +1269,12 @@ namespace EightBit
default: default:
throw new NotSupportedException("Invalid operation mode"); throw new NotSupportedException("Invalid operation mode");
} }
break; break;
default: default:
throw new NotSupportedException("Invalid operation mode"); throw new NotSupportedException("Invalid operation mode");
} }
break; break;
case 2: // Conditional jump case 2: // Conditional jump
this.JumpConditionalFlag(y); this.JumpConditionalFlag(y);
@ -1201,7 +1290,10 @@ namespace EightBit
case 1: // CB prefix case 1: // CB prefix
this.prefixCB = true; this.prefixCB = true;
if (this.displaced) if (this.displaced)
{
this.FetchDisplacement(); this.FetchDisplacement();
}
this.LowerM1(); this.LowerM1();
this.Execute(this.FetchByte()); this.Execute(this.FetchByte());
break; break;
@ -1232,10 +1324,14 @@ namespace EightBit
default: default:
throw new NotSupportedException("Invalid operation mode"); throw new NotSupportedException("Invalid operation mode");
} }
break; break;
case 4: // Conditional call: CALL cc[y], nn case 4: // Conditional call: CALL cc[y], nn
if (this.CallConditionalFlag(y)) if (this.CallConditionalFlag(y))
{
this.Tick(7); this.Tick(7);
}
this.Tick(10); this.Tick(10);
break; break;
case 5: // PUSH & various ops case 5: // PUSH & various ops
@ -1270,10 +1366,12 @@ namespace EightBit
default: default:
throw new NotSupportedException("Invalid operation mode"); throw new NotSupportedException("Invalid operation mode");
} }
break; break;
default: default:
throw new NotSupportedException("Invalid operation mode"); throw new NotSupportedException("Invalid operation mode");
} }
break; break;
case 6: case 6:
{ // Operate on accumulator and immediate operand: alu[y] n { // Operate on accumulator and immediate operand: alu[y] n
@ -1307,9 +1405,11 @@ namespace EightBit
default: default:
throw new NotSupportedException("Invalid operation mode"); throw new NotSupportedException("Invalid operation mode");
} }
this.Tick(7); this.Tick(7);
break; break;
} }
case 7: // Restart: RST y * 8 case 7: // Restart: RST y * 8
this.Restart((byte)(y << 3)); this.Restart((byte)(y << 3));
this.Tick(11); this.Tick(11);
@ -1317,6 +1417,7 @@ namespace EightBit
default: default:
throw new NotSupportedException("Invalid operation mode"); throw new NotSupportedException("Invalid operation mode");
} }
break; break;
} }
} }
@ -1475,7 +1576,7 @@ namespace EightBit
var valueNegative = value.High & (byte)StatusBits.SF; var valueNegative = value.High & (byte)StatusBits.SF;
var result = this.MEMPTR().Word - value.Word - (this.F() & (byte)StatusBits.CF); var result = this.MEMPTR().Word - value.Word - (this.F() & (byte)StatusBits.CF);
HL2().Word = (ushort)result; this.HL2().Word = (ushort)result;
var afterNegative = this.HL2().High & (byte)StatusBits.SF; var afterNegative = this.HL2().High & (byte)StatusBits.SF;
@ -1541,15 +1642,15 @@ namespace EightBit
this.F() = AdjustSZXY(this.F(), this.A() = result.Low); this.F() = AdjustSZXY(this.F(), this.A() = result.Low);
} }
private void ADC(byte value) => Add(value, this.F() & (byte)StatusBits.CF); private void ADC(byte value) => this.Add(value, this.F() & (byte)StatusBits.CF);
private void SUB(byte value, int carry = 0) private void SUB(byte value, int carry = 0)
{ {
this.A() = Subtract(this.A(), value, carry); this.A() = this.Subtract(this.A(), value, carry);
this.F() = AdjustXY(this.F(), this.A()); this.F() = AdjustXY(this.F(), this.A());
} }
private void SBC(byte value) => SUB(value, this.F() & (byte)StatusBits.CF); private void SBC(byte value) => this.SUB(value, this.F() & (byte)StatusBits.CF);
private void AndR(byte value) private void AndR(byte value)
{ {
@ -1572,7 +1673,7 @@ namespace EightBit
private void Compare(byte value) private void Compare(byte value)
{ {
this.F() = Subtract(this.A(), value); this.F() = this.Subtract(this.A(), value);
this.F() = AdjustXY(this.F(), value); this.F() = AdjustXY(this.F(), value);
} }
@ -1662,21 +1763,11 @@ namespace EightBit
this.F() = ClearFlag(this.F(), StatusBits.PF, discarded); this.F() = ClearFlag(this.F(), StatusBits.PF, discarded);
} }
private static byte RES(int n, byte operand)
{
return (byte)(operand & ~(1 << n));
}
private static byte SET(int n, byte operand)
{
return (byte)(operand | (1 << n));
}
private void DAA() private void DAA()
{ {
var updated = this.A(); var updated = this.A();
var lowAdjust = ((this.F() & (byte)StatusBits.HC) != 0) || (LowNibble(A()) > 9); var lowAdjust = ((this.F() & (byte)StatusBits.HC) != 0) || (LowNibble(this.A()) > 9);
var highAdjust = ((this.F() & (byte)StatusBits.CF) != 0) || (this.A() > 0x99); var highAdjust = ((this.F() & (byte)StatusBits.CF) != 0) || (this.A() > 0x99);
if ((this.F() & (byte)StatusBits.NF) != 0) if ((this.F() & (byte)StatusBits.NF) != 0)
@ -1768,7 +1859,7 @@ namespace EightBit
private bool CPIR() private bool CPIR()
{ {
this.CPI(); this.CPI();
return ((this.F() & (byte)StatusBits.PF) != 0) && ((this.F() & (byte)StatusBits.ZF) == 0); // See CPI return ((this.F() & (byte)StatusBits.PF) != 0) && ((this.F() & (byte)StatusBits.ZF) == 0); // See CPI
} }
private void CPD() private void CPD()
@ -1780,7 +1871,7 @@ namespace EightBit
private bool CPDR() private bool CPDR()
{ {
this.CPD(); this.CPD();
return ((this.F() & (byte)StatusBits.PF) != 0) && ((this.F() & (byte)StatusBits.ZF) == 0); // See CPD return ((this.F() & (byte)StatusBits.PF) != 0) && ((this.F() & (byte)StatusBits.ZF) == 0); // See CPD
} }
private void BlockLoad(Register16 source, Register16 destination, Register16 counter) private void BlockLoad(Register16 source, Register16 destination, Register16 counter)
@ -1790,7 +1881,7 @@ namespace EightBit
var xy = this.A() + value; var xy = this.A() + value;
this.F() = SetFlag(this.F(), StatusBits.XF, xy & (int)Bits.Bit3); this.F() = SetFlag(this.F(), StatusBits.XF, xy & (int)Bits.Bit3);
this.F() = SetFlag(this.F(), StatusBits.YF, xy & (int)Bits.Bit1); this.F() = SetFlag(this.F(), StatusBits.YF, xy & (int)Bits.Bit1);
F() = ClearFlag(this.F(), StatusBits.NF | StatusBits.HC); this.F() = ClearFlag(this.F(), StatusBits.NF | StatusBits.HC);
this.F() = SetFlag(this.F(), StatusBits.PF, --counter.Word); this.F() = SetFlag(this.F(), StatusBits.PF, --counter.Word);
} }
@ -1802,7 +1893,7 @@ namespace EightBit
private bool LDIR() private bool LDIR()
{ {
this.LDI(); this.LDI();
return (this.F() & (byte)StatusBits.PF) != 0; // See LDI return (this.F() & (byte)StatusBits.PF) != 0; // See LDI
} }
private void LDD() private void LDD()
@ -1813,7 +1904,7 @@ namespace EightBit
private bool LDDR() private bool LDDR()
{ {
this.LDD(); this.LDD();
return (this.F() & (byte)StatusBits.PF) == 0; // See LDD return (this.F() & (byte)StatusBits.PF) == 0; // See LDD
} }
private void BlockIn(Register16 source, Register16 destination) private void BlockIn(Register16 source, Register16 destination)
@ -1834,7 +1925,7 @@ namespace EightBit
private bool INIR() private bool INIR()
{ {
this.INI(); this.INI();
return (this.F() & (byte)StatusBits.ZF) == 0; // See INI return (this.F() & (byte)StatusBits.ZF) == 0; // See INI
} }
private void IND() private void IND()
@ -1846,7 +1937,7 @@ namespace EightBit
private bool INDR() private bool INDR()
{ {
this.IND(); this.IND();
return (this.F() & (byte)StatusBits.ZF) == 0; // See IND return (this.F() & (byte)StatusBits.ZF) == 0; // See IND
} }
private void BlockOut(Register16 source, Register16 destination) private void BlockOut(Register16 source, Register16 destination)
@ -1870,7 +1961,7 @@ namespace EightBit
private bool OTIR() private bool OTIR()
{ {
this.OUTI(); this.OUTI();
return (this.F() & (byte)StatusBits.ZF) == 0; // See OUTI return (this.F() & (byte)StatusBits.ZF) == 0; // See OUTI
} }
private void OUTD() private void OUTD()
@ -1882,7 +1973,7 @@ namespace EightBit
private bool OTDR() private bool OTDR()
{ {
this.OUTD(); this.OUTD();
return (this.F() & (byte)StatusBits.ZF) == 0; // See OUTD return (this.F() & (byte)StatusBits.ZF) == 0; // See OUTD
} }
private void NEG() private void NEG()