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()
{
this.OnWritingByte();
var data = this.Data; // N.B. Don't join these two lines together: the
this.Reference() = data; // data bus integrity is lost, due to evaluation order!
var value = this.Data; // N.B. Don't join these two lines together: the
this.Reference() = value; // data bus integrity is lost, due to evaluation order!
this.OnWrittenByte();
}

View File

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

View File

@ -4,7 +4,7 @@
namespace EightBit
{
public struct RefreshRegister
public struct RefreshRegister : System.IEquatable<RefreshRegister>
{
private readonly byte high;
private byte variable;
@ -37,17 +37,10 @@ namespace EightBit
public byte ToByte() => ToByte(this);
public override bool Equals(object obj)
{
if (!(obj is RefreshRegister))
{
return false;
}
var rhs = (RefreshRegister)obj;
return rhs.high == this.high && rhs.variable == this.variable;
}
public override bool Equals(object obj) => obj is RefreshRegister ? this.Equals((RefreshRegister)obj) : false;
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 prefixDD = false;
private bool prefixED = false;
private bool prefixFD = false;
private PinLevel nmiLine = PinLevel.Low;
private PinLevel m1Line = PinLevel.Low;
@ -351,7 +352,7 @@ namespace EightBit
this.OnExecutingInstruction();
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;
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.prefixCB = this.prefixDD = this.prefixED = false;
this.prefixCB = this.prefixDD = this.prefixED = this.prefixFD = false;
base.OnRaisedPOWER();
}
@ -630,80 +631,38 @@ namespace EightBit
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)
{
return this.HL;
}
0 => this.BC,
1 => this.DE,
2 => this.HL2(),
3 => this.SP,
_ => throw new ArgumentOutOfRangeException(nameof(rp)),
};
if (this.prefixDD)
{
return this.IX;
}
// Must be FD prefix
return this.IY;
}
private Register16 RP(int rp)
private Register16 RP2(int rp) => rp switch
{
switch (rp)
{
case 0:
return this.BC;
case 1:
return this.DE;
case 2:
return this.HL2();
case 3:
return this.SP;
default:
throw new ArgumentOutOfRangeException(nameof(rp));
}
}
0 => this.BC,
1 => this.DE,
2 => this.HL2(),
3 => this.AF,
_ => throw new ArgumentOutOfRangeException(nameof(rp)),
};
private Register16 RP2(int rp)
private byte R(int r) => r switch
{
switch (rp)
{
case 0:
return this.BC;
case 1:
return this.DE;
case 2:
return this.HL2();
case 3:
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));
}
}
0 => this.B,
1 => this.C,
2 => this.D,
3 => this.E,
4 => this.HL2().High,
5 => this.HL2().Low,
6 => this.BusRead(this.displaced ? this.DisplacedAddress : this.HL.Word),
7 => this.A,
_ => throw new ArgumentOutOfRangeException(nameof(r)),
};
private void R(int r, byte value)
{
@ -792,36 +751,18 @@ namespace EightBit
switch (x)
{
case 0: // rot[y] r[z]
switch (y)
operand = y switch
{
case 0:
operand = this.RLC(operand);
break;
case 1:
operand = this.RRC(operand);
break;
case 2:
operand = this.RL(operand);
break;
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");
}
0 => this.RLC(operand),
1 => this.RRC(operand),
2 => this.RL(operand),
3 => this.RR(operand),
4 => this.SLA(operand),
5 => this.SRA(operand),
6 => this.SLL(operand),
7 => this.SRL(operand),
_ => throw new NotSupportedException("Invalid operation mode"),
};
this.F = AdjustSZP(this.F, operand);
break;
case 1: // BIT y, r[z]
@ -841,11 +782,7 @@ namespace EightBit
if (update)
{
this.Tick();
if (!this.displaced)
{
this.R(z, operand);
}
else
if (this.displaced)
{
this.BusWrite(operand);
if (!memoryZ)
@ -853,6 +790,10 @@ namespace EightBit
this.R2(z, operand);
}
}
else
{
this.R(z, operand);
}
}
}
@ -885,18 +826,12 @@ namespace EightBit
this.WritePort();
break;
case 2: // 16-bit add/subtract with carry
switch (q)
this.HL2().Word = q switch
{
case 0: // SBC HL, rp[p]
this.HL2().Word = this.SBC(this.HL2(), this.RP(p));
break;
case 1: // ADC HL, rp[p]
this.HL2().Word = this.ADC(this.HL2(), this.RP(p));
break;
default:
throw new NotSupportedException("Invalid operation mode");
}
0 => this.SBC(this.HL2(), this.RP(p)), // SBC HL, rp[p]
1 => this.ADC(this.HL2(), this.RP(p)), // ADC HL, rp[p]
_ => throw new NotSupportedException("Invalid operation mode"),
};
break;
case 3: // Retrieve/store register pair from/to immediate address
this.Bus.Address.Word = this.FetchWord().Word;
@ -1412,13 +1347,10 @@ namespace EightBit
break;
case 2:
{ // 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);
@ -1563,7 +1495,7 @@ namespace EightBit
this.Execute(this.FetchInitialOpCode());
break;
case 3: // FD prefix
this.displaced = true;
this.displaced = this.prefixFD = true;
this.Execute(this.FetchInitialOpCode());
break;
default: