Apply any analysis suggestions.

Signed-off-by: Adrian Conlon <Adrian.conlon@gmail.com>
This commit is contained in:
Adrian Conlon 2019-12-04 23:23:48 +00:00
parent 73d08fe7a7
commit 2becf0e220
4 changed files with 102 additions and 201 deletions

View File

@ -66,8 +66,8 @@ namespace EightBit
public void Write() public void Write()
{ {
this.OnWritingByte(); this.OnWritingByte();
var data = this.Data; // N.B. Don't join these two lines together: the var value = this.Data; // N.B. Don't join these two lines together: the
this.Reference() = data; // data bus integrity is lost, due to evaluation order! this.Reference() = value; // data bus integrity is lost, due to evaluation order!
this.OnWrittenByte(); this.OnWrittenByte();
} }

View File

@ -4,6 +4,8 @@
namespace EightBit namespace EightBit
{ {
using System;
public class Disassembler public class Disassembler
{ {
private bool prefixCB = false; private bool prefixCB = false;
@ -29,6 +31,11 @@ namespace EightBit
public static string State(Z80 cpu) public static string State(Z80 cpu)
{ {
if (cpu == null)
{
throw new ArgumentNullException(nameof(cpu));
}
var pc = cpu.PC; var pc = cpu.PC;
var sp = cpu.SP; var sp = cpu.SP;
@ -68,59 +75,40 @@ namespace EightBit
public string Disassemble(Z80 cpu) public string Disassemble(Z80 cpu)
{ {
if (cpu == null)
{
throw new ArgumentNullException(nameof(cpu));
}
this.prefixCB = this.prefixDD = this.prefixED = this.prefixFD = false; this.prefixCB = this.prefixDD = this.prefixED = this.prefixFD = false;
return this.Disassemble(cpu, cpu.PC.Word); return this.Disassemble(cpu, cpu.PC.Word);
} }
private static string CC(int flag) private static string CC(int flag) => flag switch
{ {
switch (flag) 0 => "NZ",
{ 1 => "Z",
case 0: 2 => "NC",
return "NZ"; 3 => "C",
case 1: 4 => "PO",
return "Z"; 5 => "PE",
case 2: 6 => "P",
return "NC"; 7 => "M",
case 3: _ => throw new System.ArgumentOutOfRangeException(nameof(flag)),
return "C"; };
case 4:
return "PO";
case 5:
return "PE";
case 6:
return "P";
case 7:
return "M";
}
throw new System.ArgumentOutOfRangeException(nameof(flag)); private static string ALU(int which) => which switch
}
private static string ALU(int which)
{ {
switch (which) 0 => "ADD",
{ 1 => "ADC",
case 0: // ADD A,n 2 => "SUB",
return "ADD"; 3 => "SBC",
case 1: // ADC 4 => "AND",
return "ADC"; 5 => "XOR",
case 2: // SUB n 6 => "OR",
return "SUB"; 7 => "CP",
case 3: // SBC A,n _ => throw new System.ArgumentOutOfRangeException(nameof(which)),
return "SBC"; };
case 4: // AND n
return "AND";
case 5: // XOR n
return "XOR";
case 6: // OR n
return "OR";
case 7: // CP n
return "CP";
}
throw new System.ArgumentOutOfRangeException(nameof(which));
}
private string Disassemble(Z80 cpu, ushort pc) private string Disassemble(Z80 cpu, ushort pc)
{ {
@ -152,7 +140,7 @@ namespace EightBit
} }
else if (this.prefixED) else if (this.prefixED)
{ {
output += this.DisassembleED(cpu, pc, ref specification, ref dumpCount, x, y, z, p, q); output += this.DisassembleED(ref specification, ref dumpCount, x, y, z, p, q);
} }
else else
{ {
@ -231,7 +219,7 @@ namespace EightBit
return output; return output;
} }
private string DisassembleED(Z80 cpu, ushort pc, ref string specification, ref int dumpCount, int x, int y, int z, int p, int q) private string DisassembleED(ref string specification, ref int dumpCount, int x, int y, int z, int p, int q)
{ {
var output = string.Empty; var output = string.Empty;
switch (x) switch (x)
@ -272,15 +260,11 @@ namespace EightBit
specification = "NEG"; specification = "NEG";
break; break;
case 5: // Return from interrupt case 5: // Return from interrupt
switch (y) specification = y switch
{ {
case 1: 1 => "RETI",
specification = "RETI"; _ => "RETN",
break; };
default:
specification = "RETN";
break;
}
break; break;
case 6: // Set interrupt mode case 6: // Set interrupt mode
switch (y) switch (y)
@ -572,15 +556,7 @@ namespace EightBit
break; break;
case 1: // 8-bit loading case 1: // 8-bit loading
if (z == 6 && y == 6) specification = z == 6 && y == 6 ? "HALT" : $"LD {this.R(y)},{this.R(z)}";
{
specification = "HALT"; // Exception (replaces LD (HL), (HL))
}
else
{
specification = $"LD {this.R(y)},{this.R(z)}";
}
break; break;
case 2: // Operate on accumulator and register/memory location case 2: // Operate on accumulator and register/memory location
specification = $"{ALU(y)} A,{this.R(z)}"; specification = $"{ALU(y)} A,{this.R(z)}";

View File

@ -4,7 +4,7 @@
namespace EightBit namespace EightBit
{ {
public struct RefreshRegister public struct RefreshRegister : System.IEquatable<RefreshRegister>
{ {
private readonly byte high; private readonly byte high;
private byte variable; private byte variable;
@ -37,17 +37,10 @@ namespace EightBit
public byte ToByte() => ToByte(this); public byte ToByte() => ToByte(this);
public override bool Equals(object obj) public override bool Equals(object obj) => obj is RefreshRegister ? this.Equals((RefreshRegister)obj) : false;
{
if (!(obj is RefreshRegister))
{
return false;
}
var rhs = (RefreshRegister)obj;
return rhs.high == this.high && rhs.variable == this.variable;
}
public override int GetHashCode() => this.high + this.variable; public override int GetHashCode() => this.high + this.variable;
public bool Equals(RefreshRegister other) => other.high == this.high && other.variable == this.variable;
} }
} }

View File

@ -28,6 +28,7 @@ namespace EightBit
private bool prefixCB = false; private bool prefixCB = false;
private bool prefixDD = false; private bool prefixDD = false;
private bool prefixED = false; private bool prefixED = false;
private bool prefixFD = false;
private PinLevel nmiLine = PinLevel.Low; private PinLevel nmiLine = PinLevel.Low;
private PinLevel m1Line = PinLevel.Low; private PinLevel m1Line = PinLevel.Low;
@ -351,7 +352,7 @@ namespace EightBit
this.OnExecutingInstruction(); this.OnExecutingInstruction();
if (this.Powered) if (this.Powered)
{ {
this.displaced = this.prefixCB = this.prefixDD = this.prefixED = false; this.displaced = this.prefixCB = this.prefixDD = this.prefixED = this.prefixFD = false;
var handled = false; var handled = false;
if (this.RESET.Lowered()) if (this.RESET.Lowered())
{ {
@ -423,7 +424,7 @@ namespace EightBit
this.AF.Word = this.IX.Word = this.IY.Word = this.BC.Word = this.DE.Word = this.HL.Word = (ushort)Mask.Mask16; this.AF.Word = this.IX.Word = this.IY.Word = this.BC.Word = this.DE.Word = this.HL.Word = (ushort)Mask.Mask16;
this.prefixCB = this.prefixDD = this.prefixED = false; this.prefixCB = this.prefixDD = this.prefixED = this.prefixFD = false;
base.OnRaisedPOWER(); base.OnRaisedPOWER();
} }
@ -630,80 +631,38 @@ namespace EightBit
private void EnableInterrupts() => this.IFF1 = this.IFF2 = true; private void EnableInterrupts() => this.IFF1 = this.IFF2 = true;
private Register16 HL2() private Register16 HL2() => this.prefixDD ? this.IX : this.prefixFD ? this.IY : this.HL;
private Register16 RP(int rp) => rp switch
{ {
if (!this.displaced) 0 => this.BC,
{ 1 => this.DE,
return this.HL; 2 => this.HL2(),
} 3 => this.SP,
_ => throw new ArgumentOutOfRangeException(nameof(rp)),
};
if (this.prefixDD) private Register16 RP2(int rp) => rp switch
{
return this.IX;
}
// Must be FD prefix
return this.IY;
}
private Register16 RP(int rp)
{ {
switch (rp) 0 => this.BC,
{ 1 => this.DE,
case 0: 2 => this.HL2(),
return this.BC; 3 => this.AF,
case 1: _ => throw new ArgumentOutOfRangeException(nameof(rp)),
return this.DE; };
case 2:
return this.HL2();
case 3:
return this.SP;
default:
throw new ArgumentOutOfRangeException(nameof(rp));
}
}
private Register16 RP2(int rp) private byte R(int r) => r switch
{ {
switch (rp) 0 => this.B,
{ 1 => this.C,
case 0: 2 => this.D,
return this.BC; 3 => this.E,
case 1: 4 => this.HL2().High,
return this.DE; 5 => this.HL2().Low,
case 2: 6 => this.BusRead(this.displaced ? this.DisplacedAddress : this.HL.Word),
return this.HL2(); 7 => this.A,
case 3: _ => throw new ArgumentOutOfRangeException(nameof(r)),
return this.AF; };
default:
throw new ArgumentOutOfRangeException(nameof(rp));
}
}
private byte R(int r)
{
switch (r)
{
case 0:
return this.B;
case 1:
return this.C;
case 2:
return this.D;
case 3:
return this.E;
case 4:
return this.HL2().High;
case 5:
return this.HL2().Low;
case 6:
return this.BusRead(this.displaced ? this.DisplacedAddress : this.HL.Word);
case 7:
return this.A;
default:
throw new ArgumentOutOfRangeException(nameof(r));
}
}
private void R(int r, byte value) private void R(int r, byte value)
{ {
@ -792,36 +751,18 @@ namespace EightBit
switch (x) switch (x)
{ {
case 0: // rot[y] r[z] case 0: // rot[y] r[z]
switch (y) operand = y switch
{ {
case 0: 0 => this.RLC(operand),
operand = this.RLC(operand); 1 => this.RRC(operand),
break; 2 => this.RL(operand),
case 1: 3 => this.RR(operand),
operand = this.RRC(operand); 4 => this.SLA(operand),
break; 5 => this.SRA(operand),
case 2: 6 => this.SLL(operand),
operand = this.RL(operand); 7 => this.SRL(operand),
break; _ => throw new NotSupportedException("Invalid operation mode"),
case 3: };
operand = this.RR(operand);
break;
case 4:
operand = this.SLA(operand);
break;
case 5:
operand = this.SRA(operand);
break;
case 6:
operand = this.SLL(operand);
break;
case 7:
operand = this.SRL(operand);
break;
default:
throw new NotSupportedException("Invalid operation mode");
}
this.F = AdjustSZP(this.F, operand); this.F = AdjustSZP(this.F, operand);
break; break;
case 1: // BIT y, r[z] case 1: // BIT y, r[z]
@ -841,11 +782,7 @@ namespace EightBit
if (update) if (update)
{ {
this.Tick(); this.Tick();
if (!this.displaced) if (this.displaced)
{
this.R(z, operand);
}
else
{ {
this.BusWrite(operand); this.BusWrite(operand);
if (!memoryZ) if (!memoryZ)
@ -853,6 +790,10 @@ namespace EightBit
this.R2(z, operand); this.R2(z, operand);
} }
} }
else
{
this.R(z, operand);
}
} }
} }
@ -885,18 +826,12 @@ namespace EightBit
this.WritePort(); this.WritePort();
break; break;
case 2: // 16-bit add/subtract with carry case 2: // 16-bit add/subtract with carry
switch (q) this.HL2().Word = q switch
{ {
case 0: // SBC HL, rp[p] 0 => this.SBC(this.HL2(), this.RP(p)), // SBC HL, rp[p]
this.HL2().Word = this.SBC(this.HL2(), this.RP(p)); 1 => this.ADC(this.HL2(), this.RP(p)), // ADC HL, rp[p]
break; _ => throw new NotSupportedException("Invalid operation mode"),
case 1: // ADC HL, rp[p] };
this.HL2().Word = this.ADC(this.HL2(), this.RP(p));
break;
default:
throw new NotSupportedException("Invalid operation mode");
}
break; break;
case 3: // Retrieve/store register pair from/to immediate address case 3: // Retrieve/store register pair from/to immediate address
this.Bus.Address.Word = this.FetchWord().Word; this.Bus.Address.Word = this.FetchWord().Word;
@ -1412,13 +1347,10 @@ namespace EightBit
break; break;
case 2: case 2:
{ // Operate on accumulator and register/memory location { // Operate on accumulator and register/memory location
if (memoryZ) if (memoryZ && this.displaced)
{ {
if (this.displaced) this.FetchDisplacement();
{ this.Tick(5);
this.FetchDisplacement();
this.Tick(5);
}
} }
var value = this.R(z); var value = this.R(z);
@ -1563,7 +1495,7 @@ namespace EightBit
this.Execute(this.FetchInitialOpCode()); this.Execute(this.FetchInitialOpCode());
break; break;
case 3: // FD prefix case 3: // FD prefix
this.displaced = true; this.displaced = this.prefixFD = true;
this.Execute(this.FetchInitialOpCode()); this.Execute(this.FetchInitialOpCode());
break; break;
default: default: