Work my way through a bunch of the analysis suggestions.
Signed-off-by: Adrian Conlon <adrian.conlon@gmail.com>
This commit is contained in:
parent
db0e8c613f
commit
cd4af67177
|
@ -66,7 +66,7 @@ namespace EightBit
|
|||
public void Write()
|
||||
{
|
||||
this.OnWritingByte();
|
||||
var value = 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() = value; // data bus integrity is lost, due to evaluation order!
|
||||
this.OnWrittenByte();
|
||||
}
|
||||
|
|
|
@ -30,7 +30,7 @@ namespace EightBit
|
|||
|
||||
public static byte HighByte(ushort value) => HighByte((int)value);
|
||||
|
||||
public static byte LowByte(int value) => (byte)(value & (int)Mask.Mask8);
|
||||
public static byte LowByte(int value) => (byte)(value & (int)Mask.Eight);
|
||||
|
||||
public static byte LowByte(ushort value) => LowByte((int)value);
|
||||
|
||||
|
|
|
@ -22,6 +22,25 @@ namespace EightBit
|
|||
GC.SuppressFinalize(this);
|
||||
}
|
||||
|
||||
public IEnumerable<Tuple<ushort, byte[]>> Parse()
|
||||
{
|
||||
this.eof = false;
|
||||
while (!this.reader.EndOfStream && !this.eof)
|
||||
{
|
||||
var line = this.reader.ReadLine();
|
||||
var parsed = this.Parse(line);
|
||||
if (parsed != null)
|
||||
{
|
||||
yield return parsed;
|
||||
}
|
||||
}
|
||||
|
||||
if (!this.eof)
|
||||
{
|
||||
throw new InvalidOperationException("File is missing an EOF record");
|
||||
}
|
||||
}
|
||||
|
||||
protected virtual void Dispose(bool disposing)
|
||||
{
|
||||
if (!this.disposed)
|
||||
|
@ -35,22 +54,28 @@ namespace EightBit
|
|||
}
|
||||
}
|
||||
|
||||
public IEnumerable<Tuple<ushort, byte[]>> Parse()
|
||||
private static byte[] ParseDataRecord(string line, byte count)
|
||||
{
|
||||
this.eof = false;
|
||||
while (!this.reader.EndOfStream && !this.eof)
|
||||
if (string.IsNullOrEmpty(line))
|
||||
{
|
||||
var line = this.reader.ReadLine();
|
||||
var parsed = this.Parse(line);
|
||||
if (parsed != null)
|
||||
{
|
||||
yield return parsed;
|
||||
}
|
||||
throw new ArgumentNullException(nameof(line));
|
||||
}
|
||||
if (!this.eof)
|
||||
|
||||
var requiredLength = 9 + 2 + (count * 2);
|
||||
if (line.Length != requiredLength)
|
||||
{
|
||||
throw new InvalidOperationException("File is missing an EOF record");
|
||||
throw new ArgumentOutOfRangeException(nameof(line), "Invalid hex file: line is not the required length");
|
||||
}
|
||||
|
||||
var data = new byte[count];
|
||||
for (var i = 0; i < count; ++i)
|
||||
{
|
||||
var position = 9 + (i * 2);
|
||||
var extracted = line.Substring(position, 2);
|
||||
data[i] = Convert.ToByte(extracted, 16);
|
||||
}
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
private Tuple<ushort, byte[]> Parse(string line)
|
||||
|
@ -86,29 +111,5 @@ namespace EightBit
|
|||
throw new InvalidOperationException("Unhandled hex file record.");
|
||||
}
|
||||
}
|
||||
|
||||
private static byte[] ParseDataRecord(string line, byte count)
|
||||
{
|
||||
if (string.IsNullOrEmpty(line))
|
||||
{
|
||||
throw new ArgumentNullException(nameof(line));
|
||||
}
|
||||
|
||||
var requiredLength = 9 + 2 + (count * 2);
|
||||
if (line.Length != requiredLength)
|
||||
{
|
||||
throw new ArgumentOutOfRangeException(nameof(line), "Invalid hex file: line is not the required length");
|
||||
}
|
||||
|
||||
var data = new byte[count];
|
||||
for (var i = 0; i < count; ++i)
|
||||
{
|
||||
var position = 9 + (i * 2);
|
||||
var extracted = line.Substring(position, 2);
|
||||
data[i] = Convert.ToByte(extracted, 16);
|
||||
}
|
||||
|
||||
return data;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -32,9 +32,9 @@ namespace EightBit
|
|||
|
||||
public event EventHandler<EventArgs> LoweredHALT;
|
||||
|
||||
public Register16 SP { get; } = new Register16((ushort)Mask.Mask16);
|
||||
public Register16 SP { get; } = new Register16((ushort)Mask.Sixteen);
|
||||
|
||||
public Register16 MEMPTR { get; } = new Register16((ushort)Mask.Mask16);
|
||||
public Register16 MEMPTR { get; } = new Register16((ushort)Mask.Sixteen);
|
||||
|
||||
public abstract Register16 AF { get; }
|
||||
|
||||
|
@ -89,18 +89,18 @@ namespace EightBit
|
|||
protected static int CalculateHalfCarryAdd(byte before, byte value, int calculation)
|
||||
{
|
||||
var index = BuildHalfCarryIndex(before, value, calculation);
|
||||
return HalfCarryTableAdd[index & (int)Mask.Mask3];
|
||||
return HalfCarryTableAdd[index & (int)Mask.Three];
|
||||
}
|
||||
|
||||
protected static int CalculateHalfCarrySub(byte before, byte value, int calculation)
|
||||
{
|
||||
var index = BuildHalfCarryIndex(before, value, calculation);
|
||||
return HalfCarryTableSub[index & (int)Mask.Mask3];
|
||||
return HalfCarryTableSub[index & (int)Mask.Three];
|
||||
}
|
||||
|
||||
protected override void OnRaisedPOWER()
|
||||
{
|
||||
this.PC.Word = this.SP.Word = this.AF.Word = this.BC.Word = this.DE.Word = this.HL.Word = (ushort)Mask.Mask16;
|
||||
this.PC.Word = this.SP.Word = this.AF.Word = this.BC.Word = this.DE.Word = this.HL.Word = (ushort)Mask.Sixteen;
|
||||
this.RaiseHALT();
|
||||
base.OnRaisedPOWER();
|
||||
}
|
||||
|
|
|
@ -7,21 +7,21 @@ namespace EightBit
|
|||
public enum Mask
|
||||
{
|
||||
None = 0,
|
||||
Mask1 = Bits.Bit1 - 1,
|
||||
Mask2 = Bits.Bit2 - 1,
|
||||
Mask3 = Bits.Bit3 - 1,
|
||||
Mask4 = Bits.Bit4 - 1,
|
||||
Mask5 = Bits.Bit5 - 1,
|
||||
Mask6 = Bits.Bit6 - 1,
|
||||
Mask7 = Bits.Bit7 - 1,
|
||||
Mask8 = Bits.Bit8 - 1,
|
||||
Mask9 = Bits.Bit9 - 1,
|
||||
Mask10 = Bits.Bit10 - 1,
|
||||
Mask11 = Bits.Bit11 - 1,
|
||||
Mask12 = Bits.Bit12 - 1,
|
||||
Mask13 = Bits.Bit13 - 1,
|
||||
Mask14 = Bits.Bit14 - 1,
|
||||
Mask15 = Bits.Bit15 - 1,
|
||||
Mask16 = Bits.Bit16 - 1,
|
||||
One = Bits.Bit1 - 1,
|
||||
Two = Bits.Bit2 - 1,
|
||||
Three = Bits.Bit3 - 1,
|
||||
Four = Bits.Bit4 - 1,
|
||||
Five = Bits.Bit5 - 1,
|
||||
Six = Bits.Bit6 - 1,
|
||||
Seven = Bits.Bit7 - 1,
|
||||
Eight = Bits.Bit8 - 1,
|
||||
Nine = Bits.Bit9 - 1,
|
||||
Ten = Bits.Bit10 - 1,
|
||||
Eleven = Bits.Bit11 - 1,
|
||||
Twelve = Bits.Bit12 - 1,
|
||||
Thirteen = Bits.Bit13 - 1,
|
||||
Fourteen = Bits.Bit14 - 1,
|
||||
Fifteen = Bits.Bit15 - 1,
|
||||
Sixteen = Bits.Bit16 - 1,
|
||||
}
|
||||
}
|
||||
|
|
|
@ -11,7 +11,7 @@ namespace Fuse
|
|||
{
|
||||
private readonly List<byte> bytes = new List<byte>();
|
||||
|
||||
public ushort Address { get; private set; } = (ushort)EightBit.Mask.Mask16;
|
||||
public ushort Address { get; private set; } = (ushort)EightBit.Mask.Sixteen;
|
||||
|
||||
public ReadOnlyCollection<byte> Bytes => this.bytes.AsReadOnly();
|
||||
|
||||
|
|
|
@ -27,9 +27,9 @@ namespace Fuse
|
|||
|
||||
public string Specifier { get; private set; }
|
||||
|
||||
public ushort Address { get; private set; } = (ushort)EightBit.Mask.Mask16;
|
||||
public ushort Address { get; private set; } = (ushort)EightBit.Mask.Sixteen;
|
||||
|
||||
public byte Value { get; private set; } = (byte)EightBit.Mask.Mask8;
|
||||
public byte Value { get; private set; } = (byte)EightBit.Mask.Eight;
|
||||
|
||||
public bool TryParse(Lines lines)
|
||||
{
|
||||
|
|
|
@ -23,7 +23,7 @@ namespace Intel8080.Test
|
|||
this.ports = new InputOutput();
|
||||
this.CPU = new Intel8080(this, this.ports);
|
||||
this.disassembler = new Disassembler(this);
|
||||
this.mapping = new MemoryMapping(this.ram, 0x0000, (ushort)Mask.Mask16, AccessLevel.ReadWrite);
|
||||
this.mapping = new MemoryMapping(this.ram, 0x0000, (ushort)Mask.Sixteen, AccessLevel.ReadWrite);
|
||||
}
|
||||
|
||||
public Intel8080 CPU { get; }
|
||||
|
|
|
@ -30,11 +30,11 @@ namespace EightBit
|
|||
}
|
||||
}
|
||||
|
||||
public override Register16 BC { get; } = new Register16((int)Mask.Mask16);
|
||||
public override Register16 BC { get; } = new Register16((int)Mask.Sixteen);
|
||||
|
||||
public override Register16 DE { get; } = new Register16((int)Mask.Mask16);
|
||||
public override Register16 DE { get; } = new Register16((int)Mask.Sixteen);
|
||||
|
||||
public override Register16 HL { get; } = new Register16((int)Mask.Mask16);
|
||||
public override Register16 HL { get; } = new Register16((int)Mask.Sixteen);
|
||||
|
||||
public override int Execute()
|
||||
{
|
||||
|
@ -616,7 +616,7 @@ namespace EightBit
|
|||
private byte Decrement(byte operand)
|
||||
{
|
||||
this.F = AdjustSZP(this.F, --operand);
|
||||
this.F = SetBit(this.F, StatusBits.AC, LowNibble(operand) != (byte)Mask.Mask4);
|
||||
this.F = SetBit(this.F, StatusBits.AC, LowNibble(operand) != (byte)Mask.Four);
|
||||
return operand;
|
||||
}
|
||||
|
||||
|
|
|
@ -102,7 +102,7 @@ namespace EightBit.GameBoy
|
|||
|
||||
public void RunRasterLines()
|
||||
{
|
||||
this.enabledLCD = (this.IO.Peek(IoRegisters.LCDC) & (byte)LcdcControl.LcdEnable) != 0;
|
||||
this.enabledLCD = (this.IO.Peek(IoRegisters.LCDC) & (byte)LcdcControls.LcdEnable) != 0;
|
||||
this.IO.ResetLY();
|
||||
this.RunRasterLines(DisplayCharacteristics.RasterHeight);
|
||||
}
|
||||
|
@ -117,7 +117,7 @@ namespace EightBit.GameBoy
|
|||
{
|
||||
if ((address < 0x100) && this.IO.BootRomEnabled)
|
||||
{
|
||||
return new MemoryMapping(this.bootRom, 0x0000, Mask.Mask16, AccessLevel.ReadOnly);
|
||||
return new MemoryMapping(this.bootRom, 0x0000, Mask.Sixteen, AccessLevel.ReadOnly);
|
||||
}
|
||||
|
||||
if ((address < 0x4000) && this.GameRomEnabled)
|
||||
|
@ -198,7 +198,7 @@ namespace EightBit.GameBoy
|
|||
{
|
||||
// assert((address >= 0x2000) && (address < 0x4000));
|
||||
// assert((value > 0) && (value < 0x20));
|
||||
this.romBank = value & (byte)Mask.Mask5;
|
||||
this.romBank = value & (byte)Mask.Five;
|
||||
}
|
||||
|
||||
break;
|
||||
|
@ -214,7 +214,7 @@ namespace EightBit.GameBoy
|
|||
// Register 3: ROM/RAM change
|
||||
if (this.banked)
|
||||
{
|
||||
switch (value & (byte)Mask.Mask1)
|
||||
switch (value & (byte)Mask.One)
|
||||
{
|
||||
case 0:
|
||||
this.higherRomBank = true;
|
||||
|
|
|
@ -29,14 +29,14 @@ namespace EightBit.GameBoy
|
|||
if (this.scanLine < DisplayCharacteristics.RasterHeight)
|
||||
{
|
||||
this.control = this.bus.IO.Peek(IoRegisters.LCDC);
|
||||
if ((this.control & (byte)LcdcControl.LcdEnable) != 0)
|
||||
if ((this.control & (byte)LcdcControls.LcdEnable) != 0)
|
||||
{
|
||||
if ((this.control & (byte)LcdcControl.DisplayBackground) != 0)
|
||||
if ((this.control & (byte)LcdcControls.DisplayBackground) != 0)
|
||||
{
|
||||
this.RenderBackground();
|
||||
}
|
||||
|
||||
if ((this.control & (byte)LcdcControl.ObjectEnable) != 0)
|
||||
if ((this.control & (byte)LcdcControls.ObjectEnable) != 0)
|
||||
{
|
||||
this.RenderObjects();
|
||||
}
|
||||
|
@ -68,9 +68,9 @@ namespace EightBit.GameBoy
|
|||
{
|
||||
var palette = this.CreatePalette(IoRegisters.BGP);
|
||||
|
||||
var window = (this.control & (byte)LcdcControl.WindowEnable) != 0;
|
||||
var bgArea = (this.control & (byte)LcdcControl.BackgroundCodeAreaSelection) != 0 ? 0x1c00 : 0x1800;
|
||||
var bgCharacters = (this.control & (byte)LcdcControl.BackgroundCharacterDataSelection) != 0 ? 0 : 0x800;
|
||||
var window = (this.control & (byte)LcdcControls.WindowEnable) != 0;
|
||||
var bgArea = (this.control & (byte)LcdcControls.BackgroundCodeAreaSelection) != 0 ? 0x1c00 : 0x1800;
|
||||
var bgCharacters = (this.control & (byte)LcdcControls.BackgroundCharacterDataSelection) != 0 ? 0 : 0x800;
|
||||
|
||||
var wx = this.bus.IO.Peek(IoRegisters.WX);
|
||||
var wy = this.bus.IO.Peek(IoRegisters.WY);
|
||||
|
@ -99,7 +99,7 @@ namespace EightBit.GameBoy
|
|||
|
||||
private void RenderObjects()
|
||||
{
|
||||
var objBlockHeight = (this.control & (byte)LcdcControl.ObjectBlockCompositionSelection) != 0 ? 16 : 8;
|
||||
var objBlockHeight = (this.control & (byte)LcdcControls.ObjectBlockCompositionSelection) != 0 ? 16 : 8;
|
||||
|
||||
var palettes = new int[2][];
|
||||
palettes[0] = this.CreatePalette(IoRegisters.OBP0);
|
||||
|
|
|
@ -99,7 +99,7 @@ namespace EightBit.GameBoy
|
|||
|
||||
public bool BootRomEnabled => !this.BootRomDisabled;
|
||||
|
||||
public int TimerClock => this.TimerControl & (byte)Mask.Mask2;
|
||||
public int TimerClock => this.TimerControl & (byte)Mask.Two;
|
||||
|
||||
public bool TimerEnabled => !this.TimerDisabled;
|
||||
|
||||
|
@ -134,7 +134,7 @@ namespace EightBit.GameBoy
|
|||
public void Reset()
|
||||
{
|
||||
this.Poke(NR52, 0xf1);
|
||||
this.Poke(LCDC, (byte)(LcdcControl.DisplayBackground | LcdcControl.BackgroundCharacterDataSelection | LcdcControl.LcdEnable));
|
||||
this.Poke(LCDC, (byte)(LcdcControls.DisplayBackground | LcdcControls.BackgroundCharacterDataSelection | LcdcControls.LcdEnable));
|
||||
this.divCounter.Word = 0xabcc;
|
||||
this.timerCounter = 0;
|
||||
}
|
||||
|
@ -180,7 +180,7 @@ namespace EightBit.GameBoy
|
|||
|
||||
public void UpdateLcdStatusMode(LcdStatusMode mode)
|
||||
{
|
||||
var current = this.Peek(STAT) & unchecked((byte)~Mask.Mask2);
|
||||
var current = this.Peek(STAT) & unchecked((byte)~Mask.Two);
|
||||
this.Poke(STAT, (byte)(current | (int)mode));
|
||||
this.OnDisplayStatusModeUpdated(mode);
|
||||
}
|
||||
|
@ -364,7 +364,7 @@ namespace EightBit.GameBoy
|
|||
var upOrSelect = (live && !this.p12) ? 0 : Bits.Bit2;
|
||||
var downOrStart = (live && !this.p13) ? 0 : Bits.Bit3;
|
||||
var lowNibble = (byte)(rightOrA | leftOrB | upOrSelect | downOrStart);
|
||||
var highNibble = (byte)Chip.PromoteNibble((byte)Mask.Mask4);
|
||||
var highNibble = (byte)Chip.PromoteNibble((byte)Mask.Four);
|
||||
var value = (byte)(lowNibble | highNibble);
|
||||
this.Poke(port, value);
|
||||
}
|
||||
|
@ -382,19 +382,19 @@ namespace EightBit.GameBoy
|
|||
case TMA:
|
||||
break;
|
||||
case TAC:
|
||||
this.ApplyMask(port, (byte)Mask.Mask3);
|
||||
this.ApplyMask(port, (byte)Mask.Three);
|
||||
break;
|
||||
|
||||
// Interrupt Flags
|
||||
case IF:
|
||||
this.ApplyMask(port, (byte)Mask.Mask5);
|
||||
this.ApplyMask(port, (byte)Mask.Five);
|
||||
break;
|
||||
|
||||
// LCD Display Registers
|
||||
case LCDC:
|
||||
break;
|
||||
case STAT:
|
||||
this.ApplyMask(port, (byte)Mask.Mask7);
|
||||
this.ApplyMask(port, (byte)Mask.Seven);
|
||||
break;
|
||||
case SCY:
|
||||
case SCX:
|
||||
|
|
|
@ -11,9 +11,9 @@ namespace LR35902.BlarggTest
|
|||
var configuration = new Configuration();
|
||||
|
||||
#if DEBUG
|
||||
//configuration.DebugMode = true;
|
||||
////configuration.DebugMode = true;
|
||||
#endif
|
||||
//configuration.DebugMode = true;
|
||||
////configuration.DebugMode = true;
|
||||
|
||||
var computer = new Computer(configuration);
|
||||
|
||||
|
|
|
@ -31,7 +31,7 @@ namespace Fuse
|
|||
|
||||
public bool Unimplemented { get; private set; } = false;
|
||||
|
||||
public override EightBit.MemoryMapping Mapping(ushort address) => new EightBit.MemoryMapping(this.ram, 0, EightBit.Mask.Mask16, EightBit.AccessLevel.ReadWrite);
|
||||
public override EightBit.MemoryMapping Mapping(ushort address) => new EightBit.MemoryMapping(this.ram, 0, EightBit.Mask.Sixteen, EightBit.AccessLevel.ReadWrite);
|
||||
|
||||
public void Run()
|
||||
{
|
||||
|
|
|
@ -9,7 +9,7 @@ namespace EightBit.GameBoy
|
|||
public class LR35902 : IntelProcessor
|
||||
{
|
||||
private readonly Bus bus;
|
||||
private readonly Register16 af = new Register16((int)Mask.Mask16);
|
||||
private readonly Register16 af = new Register16((int)Mask.Sixteen);
|
||||
private bool prefixCB = false;
|
||||
|
||||
public LR35902(Bus bus)
|
||||
|
@ -30,11 +30,11 @@ namespace EightBit.GameBoy
|
|||
}
|
||||
}
|
||||
|
||||
public override Register16 BC { get; } = new Register16((int)Mask.Mask16);
|
||||
public override Register16 BC { get; } = new Register16((int)Mask.Sixteen);
|
||||
|
||||
public override Register16 DE { get; } = new Register16((int)Mask.Mask16);
|
||||
public override Register16 DE { get; } = new Register16((int)Mask.Sixteen);
|
||||
|
||||
public override Register16 HL { get; } = new Register16((int)Mask.Mask16);
|
||||
public override Register16 HL { get; } = new Register16((int)Mask.Sixteen);
|
||||
|
||||
private bool IME { get; set; } = false;
|
||||
|
||||
|
@ -123,7 +123,7 @@ namespace EightBit.GameBoy
|
|||
{
|
||||
base.HandleRESET();
|
||||
this.DI();
|
||||
this.SP.Word = (ushort)(Mask.Mask16 - 1);
|
||||
this.SP.Word = (ushort)(Mask.Sixteen - 1);
|
||||
this.Tick(4);
|
||||
}
|
||||
|
||||
|
@ -635,7 +635,7 @@ namespace EightBit.GameBoy
|
|||
var value = (sbyte)this.FetchByte();
|
||||
var result = before + value;
|
||||
this.SP.Word = (ushort)result;
|
||||
var carried = before ^ value ^ (result & (int)Mask.Mask16);
|
||||
var carried = before ^ value ^ (result & (int)Mask.Sixteen);
|
||||
this.F = ClearBit(this.F, StatusBits.ZF | StatusBits.NF);
|
||||
this.F = SetBit(this.F, StatusBits.CF, carried & (int)Bits.Bit8);
|
||||
this.F = SetBit(this.F, StatusBits.HC, carried & (int)Bits.Bit4);
|
||||
|
@ -655,7 +655,7 @@ namespace EightBit.GameBoy
|
|||
var value = (sbyte)this.FetchByte();
|
||||
var result = before + value;
|
||||
this.HL.Word = (ushort)result;
|
||||
var carried = before ^ value ^ (result & (int)Mask.Mask16);
|
||||
var carried = before ^ value ^ (result & (int)Mask.Sixteen);
|
||||
this.F = ClearBit(this.F, StatusBits.ZF | StatusBits.NF);
|
||||
this.F = SetBit(this.F, StatusBits.CF, carried & (int)Bits.Bit8);
|
||||
this.F = SetBit(this.F, StatusBits.HC, carried & (int)Bits.Bit4);
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
namespace EightBit.GameBoy
|
||||
{
|
||||
[System.Flags]
|
||||
public enum LcdcControl
|
||||
public enum LcdcControls
|
||||
{
|
||||
None = 0,
|
||||
DisplayBackground = Bits.Bit0,
|
||||
|
|
|
@ -24,9 +24,9 @@ namespace M6502.Test
|
|||
this.CPU = new M6502(this);
|
||||
this.symbols = new Symbols();
|
||||
this.disassembler = new Disassembler(this, this.CPU, this.symbols);
|
||||
this.mapping = new MemoryMapping(this.ram, 0x0000, (ushort)Mask.Mask16, AccessLevel.ReadWrite);
|
||||
this.mapping = new MemoryMapping(this.ram, 0x0000, (ushort)Mask.Sixteen, AccessLevel.ReadWrite);
|
||||
|
||||
this.oldPC = (ushort)Mask.Mask16;
|
||||
this.oldPC = (ushort)Mask.Sixteen;
|
||||
}
|
||||
|
||||
public M6502 CPU { get; }
|
||||
|
|
|
@ -555,7 +555,7 @@ namespace EightBit
|
|||
this.Y = 0;
|
||||
this.A = 0;
|
||||
this.P = (byte)StatusBits.RF;
|
||||
this.S = (byte)Mask.Mask8;
|
||||
this.S = (byte)Mask.Eight;
|
||||
this.LowerSYNC();
|
||||
this.LowerRW();
|
||||
base.OnRaisedPOWER();
|
||||
|
|
|
@ -1,4 +1,7 @@
|
|||
namespace EightBit
|
||||
// <copyright file="Disassembler.cs" company="Adrian Conlon">
|
||||
// Copyright (c) Adrian Conlon. All rights reserved.
|
||||
// </copyright>
|
||||
namespace EightBit
|
||||
{
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
@ -46,12 +49,6 @@
|
|||
|
||||
public string Trace() => this.Trace(this.CPU.PC);
|
||||
|
||||
////private static string Dump_RelativeValue(sbyte value) => value.ToString("D");
|
||||
|
||||
////private static string Dump_RelativeValue(short value) => value.ToString("D");
|
||||
|
||||
////private static string Dump_RelativeValue(Register16 value) => Dump_RelativeValue(value);
|
||||
|
||||
public string Disassemble(ushort current)
|
||||
{
|
||||
this.address = current;
|
||||
|
@ -68,26 +65,70 @@
|
|||
return this.DisassembleUnprefixed();
|
||||
}
|
||||
|
||||
private static string RR(int which)
|
||||
{
|
||||
switch (which)
|
||||
{
|
||||
case 0b00:
|
||||
return "X";
|
||||
case 0b01:
|
||||
return "Y";
|
||||
case 0b10:
|
||||
return "U";
|
||||
case 0b11:
|
||||
return "S";
|
||||
default:
|
||||
throw new ArgumentOutOfRangeException(nameof(which), which, "Register specification is unknown");
|
||||
}
|
||||
}
|
||||
|
||||
private static string WrapIndirect(string what, bool indirect)
|
||||
{
|
||||
var open = indirect ? "[" : string.Empty;
|
||||
var close = indirect ? "]" : string.Empty;
|
||||
return $"{open}{what}{close}";
|
||||
}
|
||||
|
||||
private static string ReferenceTransfer8(int specifier)
|
||||
{
|
||||
switch (specifier)
|
||||
{
|
||||
case 0b1000:
|
||||
return "A";
|
||||
case 0b1001:
|
||||
return "B";
|
||||
case 0b1010:
|
||||
return "CC";
|
||||
case 0b1011:
|
||||
return "DP";
|
||||
default:
|
||||
throw new ArgumentOutOfRangeException(nameof(specifier), specifier, "8bit register specification is unknown");
|
||||
}
|
||||
}
|
||||
|
||||
private static string ReferenceTransfer16(int specifier)
|
||||
{
|
||||
switch (specifier)
|
||||
{
|
||||
case 0b0000:
|
||||
return "D";
|
||||
case 0b0001:
|
||||
return "X";
|
||||
case 0b0010:
|
||||
return "Y";
|
||||
case 0b0011:
|
||||
return "U";
|
||||
case 0b0100:
|
||||
return "S";
|
||||
case 0b0101:
|
||||
return "PC";
|
||||
default:
|
||||
throw new ArgumentOutOfRangeException(nameof(specifier), specifier, "16bit register specification is unknown");
|
||||
}
|
||||
}
|
||||
|
||||
private string Disassemble(int current) => this.Disassemble((ushort)current);
|
||||
|
||||
////private string Dump_Flags()
|
||||
////{
|
||||
//// var returned = string.Empty;
|
||||
//// returned += this.CPU.EntireRegisterSet != 0 ? "E" : "-";
|
||||
//// returned += this.CPU.FastInterruptMasked != 0 ? "F" : "-";
|
||||
//// returned += this.CPU.HalfCarry != 0 ? "H" : "-";
|
||||
//// returned += this.CPU.InterruptMasked != 0 ? "I" : "-";
|
||||
//// returned += this.CPU.Negative != 0 ? "N" : "-";
|
||||
//// returned += this.CPU.Zero != 0 ? "Z" : "-";
|
||||
//// returned += this.CPU.Overflow != 0 ? "V" : "-";
|
||||
//// returned += this.CPU.Carry != 0 ? "C" : "-";
|
||||
//// return returned;
|
||||
////}
|
||||
|
||||
////private string Disassemble(Register16 current) => this.Disassemble(current.Word);
|
||||
|
||||
////private string Disassemble() => this.Disassemble(this.CPU.PC);
|
||||
|
||||
private string DisassembleUnprefixed()
|
||||
{
|
||||
var opcode = this.GetByte(this.address);
|
||||
|
@ -431,7 +472,6 @@
|
|||
case 0x7d: output += this.Address_extended("TST"); break; // TST (extended)
|
||||
|
||||
// Branching
|
||||
|
||||
case 0x16: output += this.BranchLong("LBRA"); break; // BRA (LBRA relative)
|
||||
case 0x17: output += this.BranchLong("LBSR"); break; // BSR (LBSR relative)
|
||||
case 0x20: output += this.BranchShort("BRA"); break; // BRA (relative)
|
||||
|
@ -496,7 +536,6 @@
|
|||
case 0xbe: output += this.Address_extended("LDY"); break; // LD (LDY extended)
|
||||
|
||||
// Branching
|
||||
|
||||
case 0x21: output += this.BranchLong("LBRN"); break; // BRN (LBRN relative)
|
||||
case 0x22: output += this.BranchLong("LBHI"); break; // BHI (LBHI relative)
|
||||
case 0x23: output += this.BranchLong("LBLS"); break; // BLS (LBLS relative)
|
||||
|
@ -568,31 +607,7 @@
|
|||
return output;
|
||||
}
|
||||
|
||||
//
|
||||
|
||||
private static string RR(int which)
|
||||
{
|
||||
switch (which)
|
||||
{
|
||||
case 0b00:
|
||||
return "X";
|
||||
case 0b01:
|
||||
return "Y";
|
||||
case 0b10:
|
||||
return "U";
|
||||
case 0b11:
|
||||
return "S";
|
||||
default:
|
||||
throw new ArgumentOutOfRangeException(nameof(which), which, "Register specification is unknown");
|
||||
}
|
||||
}
|
||||
|
||||
private static string WrapIndirect(string what, bool indirect)
|
||||
{
|
||||
var open = indirect ? "[" : "";
|
||||
var close = indirect ? "]" : "";
|
||||
return $"{open}{what}{close}";
|
||||
}
|
||||
////
|
||||
|
||||
private string Address_direct(string mnemomic)
|
||||
{
|
||||
|
@ -613,49 +628,49 @@
|
|||
if ((type & (byte)Bits.Bit7) != 0)
|
||||
{
|
||||
var indirect = (type & (byte)Bits.Bit4) != 0;
|
||||
switch (type & (byte)Mask.Mask4)
|
||||
switch (type & (byte)Mask.Four)
|
||||
{
|
||||
case 0b0000: // ,R+
|
||||
case 0b0000: // ,R+
|
||||
output += $"\t{mnemomic}\t{WrapIndirect($",{r}+", indirect)}";
|
||||
break;
|
||||
case 0b0001: // ,R++
|
||||
case 0b0001: // ,R++
|
||||
output += $"\t{mnemomic}\t{WrapIndirect($",{r}++", indirect)}";
|
||||
break;
|
||||
case 0b0010: // ,-R
|
||||
case 0b0010: // ,-R
|
||||
output += $"\t{mnemomic}\t{WrapIndirect($",-{r}", indirect)}";
|
||||
break;
|
||||
case 0b0011: // ,--R
|
||||
case 0b0011: // ,--R
|
||||
output += $"\t{mnemomic}\t{WrapIndirect($",--{r}", indirect)}";
|
||||
break;
|
||||
case 0b0100: // ,R
|
||||
case 0b0100: // ,R
|
||||
output += $"\t{mnemomic}\t{WrapIndirect($",{r}", indirect)}";
|
||||
break;
|
||||
case 0b0101: // B,R
|
||||
case 0b0101: // B,R
|
||||
output += $"\t{mnemomic}\t{WrapIndirect($"B,{r}", indirect)}";
|
||||
break;
|
||||
case 0b0110: // A,R
|
||||
case 0b0110: // A,R
|
||||
output += $"\t{mnemomic}\t{WrapIndirect($"A,{r}", indirect)}";
|
||||
break;
|
||||
case 0b1000: // n,R (eight-bit)
|
||||
case 0b1000: // n,R (eight-bit)
|
||||
byte8 = this.GetByte(++this.address);
|
||||
output += $"{byte8:x2}\t{mnemomic}\t{WrapIndirect($"{byte8:x2},{r}", indirect)}";
|
||||
break;
|
||||
case 0b1001: // n,R (sixteen-bit)
|
||||
case 0b1001: // n,R (sixteen-bit)
|
||||
word = this.GetWord(++this.address);
|
||||
output += $"{word:x4}\t{mnemomic}\t{WrapIndirect($"{word:x4},{r}", indirect)}";
|
||||
break;
|
||||
case 0b1011: // D,R
|
||||
case 0b1011: // D,R
|
||||
output += $"\t{mnemomic}\t{WrapIndirect($"D,{r}", indirect)}";
|
||||
break;
|
||||
case 0b1100: // n,PCR (eight-bit)
|
||||
case 0b1100: // n,PCR (eight-bit)
|
||||
byte8 = this.GetByte(++this.address);
|
||||
output += $"{byte8:x2}\t{mnemomic}\t{WrapIndirect("${(byte)byte8:D},PCR", indirect)}";
|
||||
break;
|
||||
case 0b1101: // n,PCR (sixteen-bit)
|
||||
case 0b1101: // n,PCR (sixteen-bit)
|
||||
word = this.GetWord(++this.address);
|
||||
output += $"{word:x4}\t{mnemomic}\t{WrapIndirect("${(short)word:D},PCR", indirect)}";
|
||||
break;
|
||||
case 0b1111: // [n]
|
||||
case 0b1111: // [n]
|
||||
if (!indirect)
|
||||
{
|
||||
throw new InvalidOperationException("Index specification cannot be direct");
|
||||
|
@ -671,7 +686,7 @@
|
|||
else
|
||||
{
|
||||
// EA = ,R + 5-bit offset
|
||||
output += $"\t{mnemomic}\t{Processor.SignExtend(5, type & (byte)Mask.Mask5)},{r}";
|
||||
output += $"\t{mnemomic}\t{Processor.SignExtend(5, type & (byte)Mask.Five)},{r}";
|
||||
}
|
||||
|
||||
return output;
|
||||
|
@ -711,44 +726,6 @@
|
|||
|
||||
private string BranchLong(string mnemomic) => this.Address_relative_word(mnemomic);
|
||||
|
||||
private static string ReferenceTransfer8(int specifier)
|
||||
{
|
||||
switch (specifier)
|
||||
{
|
||||
case 0b1000:
|
||||
return "A";
|
||||
case 0b1001:
|
||||
return "B";
|
||||
case 0b1010:
|
||||
return "CC";
|
||||
case 0b1011:
|
||||
return "DP";
|
||||
default:
|
||||
throw new ArgumentOutOfRangeException(nameof(specifier), specifier, "8bit register specification is unknown");
|
||||
}
|
||||
}
|
||||
|
||||
private static string ReferenceTransfer16(int specifier)
|
||||
{
|
||||
switch (specifier)
|
||||
{
|
||||
case 0b0000:
|
||||
return "D";
|
||||
case 0b0001:
|
||||
return "X";
|
||||
case 0b0010:
|
||||
return "Y";
|
||||
case 0b0011:
|
||||
return "U";
|
||||
case 0b0100:
|
||||
return "S";
|
||||
case 0b0101:
|
||||
return "PC";
|
||||
default:
|
||||
throw new ArgumentOutOfRangeException(nameof(specifier), specifier, "16bit register specification is unknown");
|
||||
}
|
||||
}
|
||||
|
||||
private string TFR(string mnemomic)
|
||||
{
|
||||
var data = this.GetByte(++this.address);
|
||||
|
@ -763,7 +740,7 @@
|
|||
: $"{output}{ReferenceTransfer16(reg1)},{ReferenceTransfer16(reg2)}";
|
||||
}
|
||||
|
||||
//
|
||||
////
|
||||
|
||||
private string PulS() => this.PulX("PULS", "U");
|
||||
|
||||
|
|
|
@ -40,20 +40,20 @@ namespace EightBit
|
|||
{
|
||||
if (absolute < 0x8000)
|
||||
{
|
||||
return new MemoryMapping(this.ram, 0x0000, Mask.Mask16, AccessLevel.ReadWrite);
|
||||
return new MemoryMapping(this.ram, 0x0000, Mask.Sixteen, AccessLevel.ReadWrite);
|
||||
}
|
||||
|
||||
if (absolute < 0xa000)
|
||||
{
|
||||
return new MemoryMapping(this.unused2000, 0x8000, Mask.Mask16, AccessLevel.ReadOnly);
|
||||
return new MemoryMapping(this.unused2000, 0x8000, Mask.Sixteen, AccessLevel.ReadOnly);
|
||||
}
|
||||
|
||||
if (absolute < 0xc000)
|
||||
{
|
||||
return new MemoryMapping(this.io, 0xa000, Mask.Mask16, AccessLevel.ReadWrite);
|
||||
return new MemoryMapping(this.io, 0xa000, Mask.Sixteen, AccessLevel.ReadWrite);
|
||||
}
|
||||
|
||||
return new MemoryMapping(this.rom, 0xc000, Mask.Mask16, AccessLevel.ReadOnly);
|
||||
return new MemoryMapping(this.rom, 0xc000, Mask.Sixteen, AccessLevel.ReadOnly);
|
||||
}
|
||||
|
||||
public override void RaisePOWER()
|
||||
|
|
135
MC6809/MC6809.cs
135
MC6809/MC6809.cs
|
@ -1,4 +1,7 @@
|
|||
namespace EightBit
|
||||
// <copyright file="MC6809.cs" company="Adrian Conlon">
|
||||
// Copyright (c) Adrian Conlon. All rights reserved.
|
||||
// </copyright>
|
||||
namespace EightBit
|
||||
{
|
||||
using System;
|
||||
|
||||
|
@ -6,16 +9,18 @@
|
|||
// http://www.cpu-world.com/Arch/6809.html
|
||||
// http://atjs.mbnet.fi/mc6809/Information/6809.htm
|
||||
|
||||
// |---------------|-----------------------------------|
|
||||
// | MPU State | |
|
||||
// |_______________| MPU State Definition |
|
||||
// | BA | BS | |
|
||||
// |_______|_______|___________________________________|
|
||||
// | 0 | 0 | Normal (running) |
|
||||
// | 0 | 1 | Interrupt or RESET Acknowledge |
|
||||
// | 1 | 0 | SYNC Acknowledge |
|
||||
// | 1 | 1 | HALT Acknowledge |
|
||||
// |-------|-------|-----------------------------------|
|
||||
/*
|
||||
|---------------|-----------------------------------|
|
||||
| MPU State | |
|
||||
|_______________| MPU State Definition |
|
||||
| BA | BS | |
|
||||
|_______|_______|___________________________________|
|
||||
| 0 | 0 | Normal (running) |
|
||||
| 0 | 1 | Interrupt or RESET Acknowledge |
|
||||
| 1 | 0 | SYNC Acknowledge |
|
||||
| 1 | 1 | HALT Acknowledge |
|
||||
|-------|-------|-----------------------------------|
|
||||
*/
|
||||
|
||||
public sealed class MC6809 : BigEndianProcessor
|
||||
{
|
||||
|
@ -26,7 +31,6 @@
|
|||
private const byte FIRQvector = 0xf6; // FIRQ vector
|
||||
private const byte SWI2vector = 0xf4; // SWI2 vector
|
||||
private const byte SWI3vector = 0xf2; // SWI3 vector
|
||||
// private const byte RESERVEDvector = 0xf0; // RESERVED vector
|
||||
|
||||
private byte cc = 0;
|
||||
private byte dp = 0;
|
||||
|
@ -118,6 +122,18 @@
|
|||
|
||||
public bool Halted => this.HALT.Lowered();
|
||||
|
||||
public ref PinLevel NMI => ref this.nmiLine;
|
||||
|
||||
public ref PinLevel FIRQ => ref this.firqLine;
|
||||
|
||||
public ref PinLevel HALT => ref this.haltLine;
|
||||
|
||||
public ref PinLevel BA => ref this.baLine;
|
||||
|
||||
public ref PinLevel BS => ref this.bsLine;
|
||||
|
||||
public ref PinLevel RW => ref this.rwLine;
|
||||
|
||||
public int EntireRegisterSet => this.CC & (byte)StatusBits.EF;
|
||||
|
||||
public int FastInterruptMasked => this.CC & (byte)StatusBits.FF;
|
||||
|
@ -146,18 +162,6 @@
|
|||
|
||||
private bool GT => !this.LE; // !(Z OR (N XOR V))
|
||||
|
||||
public ref PinLevel NMI => ref this.nmiLine;
|
||||
|
||||
public ref PinLevel FIRQ => ref this.firqLine;
|
||||
|
||||
public ref PinLevel HALT => ref this.haltLine;
|
||||
|
||||
public ref PinLevel BA => ref this.baLine;
|
||||
|
||||
public ref PinLevel BS => ref this.bsLine;
|
||||
|
||||
public ref PinLevel RW => ref this.rwLine;
|
||||
|
||||
public void Halt()
|
||||
{
|
||||
--this.PC.Word;
|
||||
|
@ -400,6 +404,16 @@
|
|||
return base.BusRead();
|
||||
}
|
||||
|
||||
private static byte SetBit(byte f, StatusBits flag) => SetBit(f, (byte)flag);
|
||||
|
||||
private static byte SetBit(byte f, StatusBits flag, int condition) => SetBit(f, (byte)flag, condition);
|
||||
|
||||
private static byte SetBit(byte f, StatusBits flag, bool condition) => SetBit(f, (byte)flag, condition);
|
||||
|
||||
private static byte ClearBit(byte f, StatusBits flag) => ClearBit(f, (byte)flag);
|
||||
|
||||
private static byte ClearBit(byte f, StatusBits flag, int condition) => ClearBit(f, (byte)flag, condition);
|
||||
|
||||
private void HandleHALT()
|
||||
{
|
||||
this.RaiseBA();
|
||||
|
@ -482,16 +496,6 @@
|
|||
|
||||
private void OnExecutedInstruction() => this.ExecutedInstruction?.Invoke(this, EventArgs.Empty);
|
||||
|
||||
private static byte SetBit(byte f, StatusBits flag) => SetBit(f, (byte)flag);
|
||||
|
||||
private static byte SetBit(byte f, StatusBits flag, int condition) => SetBit(f, (byte)flag, condition);
|
||||
|
||||
private static byte SetBit(byte f, StatusBits flag, bool condition) => SetBit(f, (byte)flag, condition);
|
||||
|
||||
private static byte ClearBit(byte f, StatusBits flag) => ClearBit(f, (byte)flag);
|
||||
|
||||
private static byte ClearBit(byte f, StatusBits flag, int condition) => ClearBit(f, (byte)flag, condition);
|
||||
|
||||
private void Push(Register16 stack, byte value) => this.BusWrite(--stack.Word, value);
|
||||
|
||||
private void PushS(byte value) => this.Push(this.S, value);
|
||||
|
@ -515,7 +519,8 @@
|
|||
|
||||
private Register16 RR(int which)
|
||||
{
|
||||
switch (which) {
|
||||
switch (which)
|
||||
{
|
||||
case 0b00:
|
||||
return this.X;
|
||||
case 0b01:
|
||||
|
@ -553,58 +558,58 @@
|
|||
var address = new Register16();
|
||||
if ((type & (byte)Bits.Bit7) != 0)
|
||||
{
|
||||
switch (type & (byte)Mask.Mask4)
|
||||
switch (type & (byte)Mask.Four)
|
||||
{
|
||||
case 0b0000: // ,R+
|
||||
case 0b0000: // ,R+
|
||||
this.Tick(2);
|
||||
address.Word = r.Word++;
|
||||
break;
|
||||
case 0b0001: // ,R++
|
||||
case 0b0001: // ,R++
|
||||
this.Tick(3);
|
||||
address.Word = r.Word;
|
||||
r.Word += 2;
|
||||
break;
|
||||
case 0b0010: // ,-R
|
||||
case 0b0010: // ,-R
|
||||
this.Tick(2);
|
||||
address.Word = --r.Word;
|
||||
break;
|
||||
case 0b0011: // ,--R
|
||||
case 0b0011: // ,--R
|
||||
this.Tick(3);
|
||||
r.Word -= 2;
|
||||
address.Word = r.Word;
|
||||
break;
|
||||
case 0b0100: // ,R
|
||||
case 0b0100: // ,R
|
||||
address.Word = r.Word;
|
||||
break;
|
||||
case 0b0101: // B,R
|
||||
case 0b0101: // B,R
|
||||
this.Tick();
|
||||
address.Word = (ushort)(r.Word + (sbyte)this.B);
|
||||
break;
|
||||
case 0b0110: // A,R
|
||||
case 0b0110: // A,R
|
||||
this.Tick();
|
||||
address.Word = (ushort)(r.Word + (sbyte)this.A);
|
||||
break;
|
||||
case 0b1000: // n,R (eight-bit)
|
||||
case 0b1000: // n,R (eight-bit)
|
||||
this.Tick();
|
||||
address.Word = (ushort)(r.Word + (sbyte)this.FetchByte());
|
||||
break;
|
||||
case 0b1001: // n,R (sixteen-bit)
|
||||
case 0b1001: // n,R (sixteen-bit)
|
||||
this.Tick(4);
|
||||
address.Word = (ushort)(r.Word + (short)this.FetchWord().Word);
|
||||
break;
|
||||
case 0b1011: // D,R
|
||||
case 0b1011: // D,R
|
||||
this.Tick(4);
|
||||
address.Word = (ushort)(r.Word + this.D.Word);
|
||||
break;
|
||||
case 0b1100: // n,PCR (eight-bit)
|
||||
case 0b1100: // n,PCR (eight-bit)
|
||||
this.Tick();
|
||||
address.Word = this.Address_relative_byte().Word;
|
||||
break;
|
||||
case 0b1101: // n,PCR (sixteen-bit)
|
||||
case 0b1101: // n,PCR (sixteen-bit)
|
||||
this.Tick(2);
|
||||
address.Word = this.Address_relative_word().Word;
|
||||
break;
|
||||
case 0b1111: // [n]
|
||||
case 0b1111: // [n]
|
||||
this.Tick(2);
|
||||
address.Word = this.Address_extended().Word;
|
||||
break;
|
||||
|
@ -623,8 +628,9 @@
|
|||
{
|
||||
// EA = ,R + 5-bit offset
|
||||
this.Tick();
|
||||
address.Word = new Register16(r.Word + SignExtend(5, (byte)(type & (byte)Mask.Mask5))).Word;
|
||||
address.Word = new Register16(r.Word + SignExtend(5, (byte)(type & (byte)Mask.Five))).Word;
|
||||
}
|
||||
|
||||
return address;
|
||||
}
|
||||
|
||||
|
@ -683,7 +689,7 @@
|
|||
|
||||
private byte AdjustOverflow(ushort before, ushort data, uint after)
|
||||
{
|
||||
var lowAfter = (ushort)(after & (uint)Mask.Mask16);
|
||||
var lowAfter = (ushort)(after & (uint)Mask.Sixteen);
|
||||
var highAfter = (ushort)(after >> 16);
|
||||
return SetBit(this.CC, StatusBits.VF, (before ^ data ^ lowAfter ^ (highAfter << 15)) & (int)Bits.Bit15);
|
||||
}
|
||||
|
@ -701,7 +707,7 @@
|
|||
|
||||
private byte AdjustAddition(ushort before, ushort data, uint after)
|
||||
{
|
||||
var result = new Register16(after & (uint)Mask.Mask16);
|
||||
var result = new Register16(after & (uint)Mask.Sixteen);
|
||||
this.CC = this.AdjustNZ(result);
|
||||
this.CC = this.AdjustCarry(after);
|
||||
return this.AdjustOverflow(before, data, after);
|
||||
|
@ -719,7 +725,7 @@
|
|||
|
||||
private byte AdjustSubtraction(ushort before, ushort data, uint after)
|
||||
{
|
||||
var result = new Register16(after & (uint)Mask.Mask16);
|
||||
var result = new Register16(after & (uint)Mask.Sixteen);
|
||||
this.CC = this.AdjustNZ(result);
|
||||
this.CC = this.AdjustCarry(after);
|
||||
return this.AdjustOverflow(before, data, after);
|
||||
|
@ -785,9 +791,9 @@
|
|||
this.SaveRegisterState();
|
||||
}
|
||||
|
||||
private void SaveRegisterState() => this.PSH(this.S, this.EntireRegisterSet != 0 ? (byte)Mask.Mask8 : (byte)0b10000001);
|
||||
private void SaveRegisterState() => this.PSH(this.S, this.EntireRegisterSet != 0 ? (byte)Mask.Eight : (byte)0b10000001);
|
||||
|
||||
private void RestoreRegisterState() => this.PUL(this.S, this.EntireRegisterSet != 0 ? (byte)Mask.Mask8 : (byte)0b10000001);
|
||||
private void RestoreRegisterState() => this.PUL(this.S, this.EntireRegisterSet != 0 ? (byte)Mask.Eight : (byte)0b10000001);
|
||||
|
||||
private ref byte ReferenceTransfer8(int specifier)
|
||||
{
|
||||
|
@ -808,7 +814,8 @@
|
|||
|
||||
private Register16 ReferenceTransfer16(int specifier)
|
||||
{
|
||||
switch (specifier) {
|
||||
switch (specifier)
|
||||
{
|
||||
case 0b0000:
|
||||
return this.D;
|
||||
case 0b0001:
|
||||
|
@ -1166,7 +1173,6 @@
|
|||
case 0x7d: this.Tick(7); this.TST(this.AM_extended_byte()); break; // TST (extended)
|
||||
|
||||
// Branching
|
||||
|
||||
case 0x16: this.Tick(5); this.Jump(this.Address_relative_word()); break; // BRA (LBRA relative)
|
||||
case 0x17: this.Tick(9); this.JSR(this.Address_relative_word()); break; // BSR (LBSR relative)
|
||||
case 0x20: this.Tick(3); this.Jump(this.Address_relative_byte()); break; // BRA (relative)
|
||||
|
@ -1226,7 +1232,6 @@
|
|||
case 0xbe: this.Tick(7); this.Y.Word = this.LD(this.AM_extended_word()).Word; break; // LD (LDY extended)
|
||||
|
||||
// Branching
|
||||
|
||||
case 0x21: this.Tick(5); this.Address_relative_word(); break; // BRN (LBRN relative)
|
||||
case 0x22: this.Tick(5); this.BranchLong(this.HI); break; // BHI (LBHI relative)
|
||||
case 0x23: this.Tick(5); this.BranchLong(this.LS); break; // BLS (LBLS relative)
|
||||
|
@ -1300,7 +1305,7 @@
|
|||
{
|
||||
var addition = (uint)(operand.Word + data.Word);
|
||||
this.CC = this.AdjustAddition(operand, data, addition);
|
||||
return new Register16(addition & (uint)Mask.Mask16);
|
||||
return new Register16(addition & (uint)Mask.Sixteen);
|
||||
}
|
||||
|
||||
private byte AndR(byte operand, byte data) => this.Through((byte)(operand & data));
|
||||
|
@ -1398,7 +1403,7 @@
|
|||
{
|
||||
ref var rightRegister = ref this.ReferenceTransfer8(rightSpecifier);
|
||||
(leftRegister.Low, rightRegister) = (rightRegister, leftRegister.Low);
|
||||
leftRegister.High = (byte)Mask.Mask8;
|
||||
leftRegister.High = (byte)Mask.Eight;
|
||||
}
|
||||
}
|
||||
else
|
||||
|
@ -1408,7 +1413,7 @@
|
|||
{
|
||||
var rightRegister = this.ReferenceTransfer16(rightSpecifier);
|
||||
(leftRegister, rightRegister.Low) = (rightRegister.Low, leftRegister);
|
||||
rightRegister.High =(byte)Mask.Mask8;
|
||||
rightRegister.High =(byte)Mask.Eight;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -1470,6 +1475,7 @@
|
|||
if ((data & (byte)Bits.Bit6) != 0)
|
||||
{
|
||||
this.Tick(2);
|
||||
|
||||
// Pushing to the S stack means we must be pushing U
|
||||
this.PushWord(stack, object.ReferenceEquals(stack, this.S) ? this.U : this.S);
|
||||
}
|
||||
|
@ -1552,6 +1558,7 @@
|
|||
if ((data & (byte)Bits.Bit6) != 0)
|
||||
{
|
||||
this.Tick(2);
|
||||
|
||||
// Pulling from the S stack means we must be pulling U
|
||||
(object.ReferenceEquals(stack, this.S) ? this.U : this.S).Word = this.PopWord(stack).Word;
|
||||
}
|
||||
|
@ -1599,13 +1606,13 @@
|
|||
{
|
||||
var subtraction = (uint)(operand.Word - data.Word);
|
||||
this.CC = this.AdjustSubtraction(operand, data, subtraction);
|
||||
return new Register16(subtraction & (uint)Mask.Mask16);
|
||||
return new Register16(subtraction & (uint)Mask.Sixteen);
|
||||
}
|
||||
|
||||
private byte SEX(byte from)
|
||||
{
|
||||
this.CC = this.AdjustNZ(from);
|
||||
return (from & (byte)Bits.Bit7) != 0 ? (byte)Mask.Mask8 : (byte)0;
|
||||
return (from & (byte)Bits.Bit7) != 0 ? (byte)Mask.Eight : (byte)0;
|
||||
}
|
||||
|
||||
private void SWI()
|
||||
|
@ -1657,7 +1664,7 @@
|
|||
{
|
||||
var destinationRegister = this.ReferenceTransfer16(destinationSpecifier);
|
||||
destinationRegister.Low = sourceRegister;
|
||||
destinationRegister.High = (byte)Mask.Mask8;
|
||||
destinationRegister.High = (byte)Mask.Eight;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
|
@ -1,4 +1,7 @@
|
|||
namespace EightBit
|
||||
// <copyright file="ProfileEventArgs.cs" company="Adrian Conlon">
|
||||
// Copyright (c) Adrian Conlon. All rights reserved.
|
||||
// </copyright>
|
||||
namespace EightBit
|
||||
{
|
||||
using System;
|
||||
|
||||
|
|
|
@ -1,4 +1,7 @@
|
|||
namespace EightBit
|
||||
// <copyright file="ProfileLineEventArgs.cs" company="Adrian Conlon">
|
||||
// Copyright (c) Adrian Conlon. All rights reserved.
|
||||
// </copyright>
|
||||
namespace EightBit
|
||||
{
|
||||
using System;
|
||||
|
||||
|
|
|
@ -1,4 +1,7 @@
|
|||
namespace EightBit
|
||||
// <copyright file="ProfileScopeEventArgs.cs" company="Adrian Conlon">
|
||||
// Copyright (c) Adrian Conlon. All rights reserved.
|
||||
// </copyright>
|
||||
namespace EightBit
|
||||
{
|
||||
using System;
|
||||
|
||||
|
|
|
@ -1,4 +1,7 @@
|
|||
namespace EightBit
|
||||
// <copyright file="Profiler.cs" company="Adrian Conlon">
|
||||
// Copyright (c) Adrian Conlon. All rights reserved.
|
||||
// </copyright>
|
||||
namespace EightBit
|
||||
{
|
||||
using System;
|
||||
|
||||
|
@ -8,12 +11,12 @@
|
|||
private readonly ulong[] addressProfiles;
|
||||
private readonly ulong[] addressCounts;
|
||||
|
||||
private ushort address;
|
||||
|
||||
private readonly Bus board;
|
||||
private readonly MC6809 processor;
|
||||
private readonly Disassembler disassembler;
|
||||
|
||||
private ushort address;
|
||||
|
||||
public Profiler(Bus board, MC6809 processor, Disassembler disassembler)
|
||||
{
|
||||
this.board = board;
|
||||
|
|
|
@ -1,4 +1,7 @@
|
|||
using System.Reflection;
|
||||
// <copyright file="AssemblyInfo.cs" company="Adrian Conlon">
|
||||
// Copyright (c) Adrian Conlon. All rights reserved.
|
||||
// </copyright>
|
||||
using System.Reflection;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
|
|
|
@ -284,6 +284,7 @@ namespace EightBit
|
|||
specification = "IM 2";
|
||||
break;
|
||||
}
|
||||
|
||||
break;
|
||||
case 7:
|
||||
switch (y)
|
||||
|
|
|
@ -12,7 +12,7 @@ namespace EightBit
|
|||
public RefreshRegister(byte value)
|
||||
{
|
||||
this.high = (byte)(value & (byte)Bits.Bit7);
|
||||
this.variable = (byte)(value & (byte)Mask.Mask7);
|
||||
this.variable = (byte)(value & (byte)Mask.Seven);
|
||||
}
|
||||
|
||||
public static implicit operator byte(RefreshRegister input) => ToByte(input);
|
||||
|
@ -25,7 +25,7 @@ namespace EightBit
|
|||
|
||||
public static bool operator !=(RefreshRegister left, RefreshRegister right) => !(left == right);
|
||||
|
||||
public static byte ToByte(RefreshRegister input) => (byte)(input.high | (input.variable & (byte)Mask.Mask7));
|
||||
public static byte ToByte(RefreshRegister input) => (byte)(input.high | (input.variable & (byte)Mask.Seven));
|
||||
|
||||
public static RefreshRegister Increment(RefreshRegister value)
|
||||
{
|
||||
|
|
|
@ -27,7 +27,7 @@ namespace EightBit
|
|||
// Parity
|
||||
PF = Bits.Bit2,
|
||||
|
||||
// Zero
|
||||
// Overflow
|
||||
VF = Bits.Bit2,
|
||||
|
||||
// Negative?
|
||||
|
|
|
@ -44,7 +44,7 @@ namespace Fuse
|
|||
foreach (var e in result.Events.Container)
|
||||
{
|
||||
// Ignore contention events
|
||||
if (!e.Specifier.EndsWith("C"))
|
||||
if (!e.Specifier.EndsWith("C", System.StringComparison.Ordinal))
|
||||
{
|
||||
this.expectedEvents.Add(e);
|
||||
}
|
||||
|
@ -55,7 +55,7 @@ namespace Fuse
|
|||
|
||||
public bool Unimplemented { get; private set; } = false;
|
||||
|
||||
public override EightBit.MemoryMapping Mapping(ushort address) => new EightBit.MemoryMapping(this.ram, 0, EightBit.Mask.Mask16, EightBit.AccessLevel.ReadWrite);
|
||||
public override EightBit.MemoryMapping Mapping(ushort address) => new EightBit.MemoryMapping(this.ram, 0, EightBit.Mask.Sixteen, EightBit.AccessLevel.ReadWrite);
|
||||
|
||||
public void Run()
|
||||
{
|
||||
|
@ -446,7 +446,7 @@ namespace Fuse
|
|||
private static string ToString(TestEvent e)
|
||||
{
|
||||
var output = $"Cycles = {e.Cycles}, Specifier = {e.Specifier}, Address = {e.Address:X4}";
|
||||
if (!e.Specifier.EndsWith("C"))
|
||||
if (!e.Specifier.EndsWith("C", System.StringComparison.Ordinal))
|
||||
{
|
||||
output += $", Value={e.Value:X2}";
|
||||
}
|
||||
|
|
|
@ -23,7 +23,7 @@ namespace Z80.Test
|
|||
this.ports = new InputOutput();
|
||||
this.CPU = new Z80(this, this.ports);
|
||||
this.disassembler = new Disassembler(this);
|
||||
this.mapping = new MemoryMapping(this.ram, 0x0000, (ushort)Mask.Mask16, AccessLevel.ReadWrite);
|
||||
this.mapping = new MemoryMapping(this.ram, 0x0000, (ushort)Mask.Sixteen, AccessLevel.ReadWrite);
|
||||
}
|
||||
|
||||
public Z80 CPU { get; }
|
||||
|
|
16
Z80/Z80.cs
16
Z80/Z80.cs
|
@ -417,12 +417,12 @@ namespace EightBit
|
|||
this.IM = 0;
|
||||
|
||||
this.REFRESH = new RefreshRegister(0);
|
||||
this.IV = (byte)Mask.Mask8;
|
||||
this.IV = (byte)Mask.Eight;
|
||||
|
||||
this.ExxAF();
|
||||
this.Exx();
|
||||
|
||||
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.Sixteen;
|
||||
|
||||
this.prefixCB = this.prefixDD = this.prefixED = this.prefixFD = false;
|
||||
|
||||
|
@ -519,7 +519,7 @@ namespace EightBit
|
|||
base.HandleRESET();
|
||||
this.DisableInterrupts();
|
||||
this.IV = this.REFRESH = 0;
|
||||
this.SP.Word = this.AF.Word = (ushort)Mask.Mask16;
|
||||
this.SP.Word = this.AF.Word = (ushort)Mask.Sixteen;
|
||||
this.Tick(3);
|
||||
}
|
||||
|
||||
|
@ -1035,6 +1035,7 @@ namespace EightBit
|
|||
this.PC.Word -= 2;
|
||||
this.Tick(5);
|
||||
}
|
||||
|
||||
this.Tick(3);
|
||||
break;
|
||||
case 7: // OTDR
|
||||
|
@ -1043,6 +1044,7 @@ namespace EightBit
|
|||
this.PC.Word -= 2;
|
||||
this.Tick(5);
|
||||
}
|
||||
|
||||
this.Tick(3);
|
||||
break;
|
||||
}
|
||||
|
@ -1200,6 +1202,7 @@ namespace EightBit
|
|||
this.R(y, this.Increment(original));
|
||||
break;
|
||||
}
|
||||
|
||||
case 5: // 8-bit DEC
|
||||
{
|
||||
if (memoryY && this.displaced)
|
||||
|
@ -1230,6 +1233,7 @@ namespace EightBit
|
|||
this.R(y, value); // LD r,n
|
||||
break;
|
||||
}
|
||||
|
||||
case 7: // Assorted operations on accumulator/flags
|
||||
switch (y)
|
||||
{
|
||||
|
@ -1634,7 +1638,7 @@ namespace EightBit
|
|||
this.F = ClearBit(this.F, StatusBits.HC, LowNibble(operand));
|
||||
var result = --operand;
|
||||
this.F = AdjustSZXY(this.F, result);
|
||||
this.F = SetBit(this.F, StatusBits.VF, result == (byte)Mask.Mask7);
|
||||
this.F = SetBit(this.F, StatusBits.VF, result == (byte)Mask.Seven);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
@ -1697,7 +1701,7 @@ namespace EightBit
|
|||
return this.intermediate.Word;
|
||||
}
|
||||
|
||||
private ushort ADC(Register16 operand ,Register16 value)
|
||||
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);
|
||||
|
@ -2049,7 +2053,7 @@ namespace EightBit
|
|||
this.MEMPTR.Word = destination.Word;
|
||||
this.F = SetBit(this.F, StatusBits.NF, value & (byte)Bits.Bit7);
|
||||
this.F = SetBit(this.F, StatusBits.HC | StatusBits.CF, (this.L + value) > 0xff);
|
||||
this.F = AdjustParity(this.F, (byte)(((value + this.L) & (int)Mask.Mask3) ^ this.B));
|
||||
this.F = AdjustParity(this.F, (byte)(((value + this.L) & (int)Mask.Three) ^ this.B));
|
||||
}
|
||||
|
||||
private void OUTI()
|
||||
|
|
Loading…
Reference in New Issue