Work my way through a bunch of the analysis suggestions.

Signed-off-by: Adrian Conlon <adrian.conlon@gmail.com>
This commit is contained in:
Adrian Conlon 2020-06-22 00:00:15 +01:00
parent db0e8c613f
commit cd4af67177
32 changed files with 297 additions and 292 deletions

View File

@ -66,7 +66,7 @@ namespace EightBit
public void Write() public void Write()
{ {
this.OnWritingByte(); 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.Reference() = value; // data bus integrity is lost, due to evaluation order!
this.OnWrittenByte(); this.OnWrittenByte();
} }

View File

@ -30,7 +30,7 @@ namespace EightBit
public static byte HighByte(ushort value) => HighByte((int)value); 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); public static byte LowByte(ushort value) => LowByte((int)value);

View File

@ -22,6 +22,25 @@ namespace EightBit
GC.SuppressFinalize(this); 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) protected virtual void Dispose(bool disposing)
{ {
if (!this.disposed) 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; if (string.IsNullOrEmpty(line))
while (!this.reader.EndOfStream && !this.eof)
{ {
var line = this.reader.ReadLine(); throw new ArgumentNullException(nameof(line));
var parsed = this.Parse(line);
if (parsed != null)
{
yield return parsed;
}
} }
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) private Tuple<ushort, byte[]> Parse(string line)
@ -86,29 +111,5 @@ namespace EightBit
throw new InvalidOperationException("Unhandled hex file record."); 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;
}
} }
} }

View File

@ -32,9 +32,9 @@ namespace EightBit
public event EventHandler<EventArgs> LoweredHALT; 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; } public abstract Register16 AF { get; }
@ -89,18 +89,18 @@ namespace EightBit
protected static int CalculateHalfCarryAdd(byte before, byte value, int calculation) protected static int CalculateHalfCarryAdd(byte before, byte value, int calculation)
{ {
var index = BuildHalfCarryIndex(before, value, 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) protected static int CalculateHalfCarrySub(byte before, byte value, int calculation)
{ {
var index = BuildHalfCarryIndex(before, value, calculation); var index = BuildHalfCarryIndex(before, value, calculation);
return HalfCarryTableSub[index & (int)Mask.Mask3]; return HalfCarryTableSub[index & (int)Mask.Three];
} }
protected override void OnRaisedPOWER() 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(); this.RaiseHALT();
base.OnRaisedPOWER(); base.OnRaisedPOWER();
} }

View File

@ -7,21 +7,21 @@ namespace EightBit
public enum Mask public enum Mask
{ {
None = 0, None = 0,
Mask1 = Bits.Bit1 - 1, One = Bits.Bit1 - 1,
Mask2 = Bits.Bit2 - 1, Two = Bits.Bit2 - 1,
Mask3 = Bits.Bit3 - 1, Three = Bits.Bit3 - 1,
Mask4 = Bits.Bit4 - 1, Four = Bits.Bit4 - 1,
Mask5 = Bits.Bit5 - 1, Five = Bits.Bit5 - 1,
Mask6 = Bits.Bit6 - 1, Six = Bits.Bit6 - 1,
Mask7 = Bits.Bit7 - 1, Seven = Bits.Bit7 - 1,
Mask8 = Bits.Bit8 - 1, Eight = Bits.Bit8 - 1,
Mask9 = Bits.Bit9 - 1, Nine = Bits.Bit9 - 1,
Mask10 = Bits.Bit10 - 1, Ten = Bits.Bit10 - 1,
Mask11 = Bits.Bit11 - 1, Eleven = Bits.Bit11 - 1,
Mask12 = Bits.Bit12 - 1, Twelve = Bits.Bit12 - 1,
Mask13 = Bits.Bit13 - 1, Thirteen = Bits.Bit13 - 1,
Mask14 = Bits.Bit14 - 1, Fourteen = Bits.Bit14 - 1,
Mask15 = Bits.Bit15 - 1, Fifteen = Bits.Bit15 - 1,
Mask16 = Bits.Bit16 - 1, Sixteen = Bits.Bit16 - 1,
} }
} }

View File

@ -11,7 +11,7 @@ namespace Fuse
{ {
private readonly List<byte> bytes = new List<byte>(); 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(); public ReadOnlyCollection<byte> Bytes => this.bytes.AsReadOnly();

View File

@ -27,9 +27,9 @@ namespace Fuse
public string Specifier { get; private set; } 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) public bool TryParse(Lines lines)
{ {

View File

@ -23,7 +23,7 @@ namespace Intel8080.Test
this.ports = new InputOutput(); this.ports = new InputOutput();
this.CPU = new Intel8080(this, this.ports); this.CPU = new Intel8080(this, this.ports);
this.disassembler = new Disassembler(this); 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; } public Intel8080 CPU { get; }

View File

@ -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() public override int Execute()
{ {
@ -616,7 +616,7 @@ namespace EightBit
private byte Decrement(byte operand) private byte Decrement(byte operand)
{ {
this.F = AdjustSZP(this.F, --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; return operand;
} }

View File

@ -102,7 +102,7 @@ namespace EightBit.GameBoy
public void RunRasterLines() 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.IO.ResetLY();
this.RunRasterLines(DisplayCharacteristics.RasterHeight); this.RunRasterLines(DisplayCharacteristics.RasterHeight);
} }
@ -117,7 +117,7 @@ namespace EightBit.GameBoy
{ {
if ((address < 0x100) && this.IO.BootRomEnabled) 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) if ((address < 0x4000) && this.GameRomEnabled)
@ -198,7 +198,7 @@ namespace EightBit.GameBoy
{ {
// assert((address >= 0x2000) && (address < 0x4000)); // assert((address >= 0x2000) && (address < 0x4000));
// assert((value > 0) && (value < 0x20)); // assert((value > 0) && (value < 0x20));
this.romBank = value & (byte)Mask.Mask5; this.romBank = value & (byte)Mask.Five;
} }
break; break;
@ -214,7 +214,7 @@ namespace EightBit.GameBoy
// Register 3: ROM/RAM change // Register 3: ROM/RAM change
if (this.banked) if (this.banked)
{ {
switch (value & (byte)Mask.Mask1) switch (value & (byte)Mask.One)
{ {
case 0: case 0:
this.higherRomBank = true; this.higherRomBank = true;

View File

@ -29,14 +29,14 @@ namespace EightBit.GameBoy
if (this.scanLine < DisplayCharacteristics.RasterHeight) if (this.scanLine < DisplayCharacteristics.RasterHeight)
{ {
this.control = this.bus.IO.Peek(IoRegisters.LCDC); 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(); this.RenderBackground();
} }
if ((this.control & (byte)LcdcControl.ObjectEnable) != 0) if ((this.control & (byte)LcdcControls.ObjectEnable) != 0)
{ {
this.RenderObjects(); this.RenderObjects();
} }
@ -68,9 +68,9 @@ namespace EightBit.GameBoy
{ {
var palette = this.CreatePalette(IoRegisters.BGP); var palette = this.CreatePalette(IoRegisters.BGP);
var window = (this.control & (byte)LcdcControl.WindowEnable) != 0; var window = (this.control & (byte)LcdcControls.WindowEnable) != 0;
var bgArea = (this.control & (byte)LcdcControl.BackgroundCodeAreaSelection) != 0 ? 0x1c00 : 0x1800; var bgArea = (this.control & (byte)LcdcControls.BackgroundCodeAreaSelection) != 0 ? 0x1c00 : 0x1800;
var bgCharacters = (this.control & (byte)LcdcControl.BackgroundCharacterDataSelection) != 0 ? 0 : 0x800; var bgCharacters = (this.control & (byte)LcdcControls.BackgroundCharacterDataSelection) != 0 ? 0 : 0x800;
var wx = this.bus.IO.Peek(IoRegisters.WX); var wx = this.bus.IO.Peek(IoRegisters.WX);
var wy = this.bus.IO.Peek(IoRegisters.WY); var wy = this.bus.IO.Peek(IoRegisters.WY);
@ -99,7 +99,7 @@ namespace EightBit.GameBoy
private void RenderObjects() 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][]; var palettes = new int[2][];
palettes[0] = this.CreatePalette(IoRegisters.OBP0); palettes[0] = this.CreatePalette(IoRegisters.OBP0);

View File

@ -99,7 +99,7 @@ namespace EightBit.GameBoy
public bool BootRomEnabled => !this.BootRomDisabled; 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; public bool TimerEnabled => !this.TimerDisabled;
@ -134,7 +134,7 @@ namespace EightBit.GameBoy
public void Reset() public void Reset()
{ {
this.Poke(NR52, 0xf1); 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.divCounter.Word = 0xabcc;
this.timerCounter = 0; this.timerCounter = 0;
} }
@ -180,7 +180,7 @@ namespace EightBit.GameBoy
public void UpdateLcdStatusMode(LcdStatusMode mode) 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.Poke(STAT, (byte)(current | (int)mode));
this.OnDisplayStatusModeUpdated(mode); this.OnDisplayStatusModeUpdated(mode);
} }
@ -364,7 +364,7 @@ namespace EightBit.GameBoy
var upOrSelect = (live && !this.p12) ? 0 : Bits.Bit2; var upOrSelect = (live && !this.p12) ? 0 : Bits.Bit2;
var downOrStart = (live && !this.p13) ? 0 : Bits.Bit3; var downOrStart = (live && !this.p13) ? 0 : Bits.Bit3;
var lowNibble = (byte)(rightOrA | leftOrB | upOrSelect | downOrStart); 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); var value = (byte)(lowNibble | highNibble);
this.Poke(port, value); this.Poke(port, value);
} }
@ -382,19 +382,19 @@ namespace EightBit.GameBoy
case TMA: case TMA:
break; break;
case TAC: case TAC:
this.ApplyMask(port, (byte)Mask.Mask3); this.ApplyMask(port, (byte)Mask.Three);
break; break;
// Interrupt Flags // Interrupt Flags
case IF: case IF:
this.ApplyMask(port, (byte)Mask.Mask5); this.ApplyMask(port, (byte)Mask.Five);
break; break;
// LCD Display Registers // LCD Display Registers
case LCDC: case LCDC:
break; break;
case STAT: case STAT:
this.ApplyMask(port, (byte)Mask.Mask7); this.ApplyMask(port, (byte)Mask.Seven);
break; break;
case SCY: case SCY:
case SCX: case SCX:

View File

@ -11,9 +11,9 @@ namespace LR35902.BlarggTest
var configuration = new Configuration(); var configuration = new Configuration();
#if DEBUG #if DEBUG
//configuration.DebugMode = true; ////configuration.DebugMode = true;
#endif #endif
//configuration.DebugMode = true; ////configuration.DebugMode = true;
var computer = new Computer(configuration); var computer = new Computer(configuration);

View File

@ -31,7 +31,7 @@ namespace Fuse
public bool Unimplemented { get; private set; } = false; 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() public void Run()
{ {

View File

@ -9,7 +9,7 @@ namespace EightBit.GameBoy
public class LR35902 : IntelProcessor public class LR35902 : IntelProcessor
{ {
private readonly Bus bus; 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; private bool prefixCB = false;
public LR35902(Bus bus) 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; private bool IME { get; set; } = false;
@ -123,7 +123,7 @@ namespace EightBit.GameBoy
{ {
base.HandleRESET(); base.HandleRESET();
this.DI(); this.DI();
this.SP.Word = (ushort)(Mask.Mask16 - 1); this.SP.Word = (ushort)(Mask.Sixteen - 1);
this.Tick(4); this.Tick(4);
} }
@ -635,7 +635,7 @@ namespace EightBit.GameBoy
var value = (sbyte)this.FetchByte(); var value = (sbyte)this.FetchByte();
var result = before + value; var result = before + value;
this.SP.Word = (ushort)result; 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 = ClearBit(this.F, StatusBits.ZF | StatusBits.NF);
this.F = SetBit(this.F, StatusBits.CF, carried & (int)Bits.Bit8); this.F = SetBit(this.F, StatusBits.CF, carried & (int)Bits.Bit8);
this.F = SetBit(this.F, StatusBits.HC, carried & (int)Bits.Bit4); this.F = SetBit(this.F, StatusBits.HC, carried & (int)Bits.Bit4);
@ -655,7 +655,7 @@ namespace EightBit.GameBoy
var value = (sbyte)this.FetchByte(); var value = (sbyte)this.FetchByte();
var result = before + value; var result = before + value;
this.HL.Word = (ushort)result; 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 = ClearBit(this.F, StatusBits.ZF | StatusBits.NF);
this.F = SetBit(this.F, StatusBits.CF, carried & (int)Bits.Bit8); this.F = SetBit(this.F, StatusBits.CF, carried & (int)Bits.Bit8);
this.F = SetBit(this.F, StatusBits.HC, carried & (int)Bits.Bit4); this.F = SetBit(this.F, StatusBits.HC, carried & (int)Bits.Bit4);

View File

@ -4,7 +4,7 @@
namespace EightBit.GameBoy namespace EightBit.GameBoy
{ {
[System.Flags] [System.Flags]
public enum LcdcControl public enum LcdcControls
{ {
None = 0, None = 0,
DisplayBackground = Bits.Bit0, DisplayBackground = Bits.Bit0,

View File

@ -24,9 +24,9 @@ namespace M6502.Test
this.CPU = new M6502(this); this.CPU = new M6502(this);
this.symbols = new Symbols(); this.symbols = new Symbols();
this.disassembler = new Disassembler(this, this.CPU, this.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; } public M6502 CPU { get; }

View File

@ -555,7 +555,7 @@ namespace EightBit
this.Y = 0; this.Y = 0;
this.A = 0; this.A = 0;
this.P = (byte)StatusBits.RF; this.P = (byte)StatusBits.RF;
this.S = (byte)Mask.Mask8; this.S = (byte)Mask.Eight;
this.LowerSYNC(); this.LowerSYNC();
this.LowerRW(); this.LowerRW();
base.OnRaisedPOWER(); base.OnRaisedPOWER();

View File

@ -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;
using System.Collections.Generic; using System.Collections.Generic;
@ -46,12 +49,6 @@
public string Trace() => this.Trace(this.CPU.PC); 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) public string Disassemble(ushort current)
{ {
this.address = current; this.address = current;
@ -68,26 +65,70 @@
return this.DisassembleUnprefixed(); 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 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() private string DisassembleUnprefixed()
{ {
var opcode = this.GetByte(this.address); var opcode = this.GetByte(this.address);
@ -431,7 +472,6 @@
case 0x7d: output += this.Address_extended("TST"); break; // TST (extended) case 0x7d: output += this.Address_extended("TST"); break; // TST (extended)
// Branching // Branching
case 0x16: output += this.BranchLong("LBRA"); break; // BRA (LBRA relative) case 0x16: output += this.BranchLong("LBRA"); break; // BRA (LBRA relative)
case 0x17: output += this.BranchLong("LBSR"); break; // BSR (LBSR relative) case 0x17: output += this.BranchLong("LBSR"); break; // BSR (LBSR relative)
case 0x20: output += this.BranchShort("BRA"); break; // BRA (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) case 0xbe: output += this.Address_extended("LDY"); break; // LD (LDY extended)
// Branching // Branching
case 0x21: output += this.BranchLong("LBRN"); break; // BRN (LBRN relative) case 0x21: output += this.BranchLong("LBRN"); break; // BRN (LBRN relative)
case 0x22: output += this.BranchLong("LBHI"); break; // BHI (LBHI relative) case 0x22: output += this.BranchLong("LBHI"); break; // BHI (LBHI relative)
case 0x23: output += this.BranchLong("LBLS"); break; // BLS (LBLS relative) case 0x23: output += this.BranchLong("LBLS"); break; // BLS (LBLS relative)
@ -568,31 +607,7 @@
return output; 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) private string Address_direct(string mnemomic)
{ {
@ -613,49 +628,49 @@
if ((type & (byte)Bits.Bit7) != 0) if ((type & (byte)Bits.Bit7) != 0)
{ {
var indirect = (type & (byte)Bits.Bit4) != 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)}"; output += $"\t{mnemomic}\t{WrapIndirect($",{r}+", indirect)}";
break; break;
case 0b0001: // ,R++ case 0b0001: // ,R++
output += $"\t{mnemomic}\t{WrapIndirect($",{r}++", indirect)}"; output += $"\t{mnemomic}\t{WrapIndirect($",{r}++", indirect)}";
break; break;
case 0b0010: // ,-R case 0b0010: // ,-R
output += $"\t{mnemomic}\t{WrapIndirect($",-{r}", indirect)}"; output += $"\t{mnemomic}\t{WrapIndirect($",-{r}", indirect)}";
break; break;
case 0b0011: // ,--R case 0b0011: // ,--R
output += $"\t{mnemomic}\t{WrapIndirect($",--{r}", indirect)}"; output += $"\t{mnemomic}\t{WrapIndirect($",--{r}", indirect)}";
break; break;
case 0b0100: // ,R case 0b0100: // ,R
output += $"\t{mnemomic}\t{WrapIndirect($",{r}", indirect)}"; output += $"\t{mnemomic}\t{WrapIndirect($",{r}", indirect)}";
break; break;
case 0b0101: // B,R case 0b0101: // B,R
output += $"\t{mnemomic}\t{WrapIndirect($"B,{r}", indirect)}"; output += $"\t{mnemomic}\t{WrapIndirect($"B,{r}", indirect)}";
break; break;
case 0b0110: // A,R case 0b0110: // A,R
output += $"\t{mnemomic}\t{WrapIndirect($"A,{r}", indirect)}"; output += $"\t{mnemomic}\t{WrapIndirect($"A,{r}", indirect)}";
break; break;
case 0b1000: // n,R (eight-bit) case 0b1000: // n,R (eight-bit)
byte8 = this.GetByte(++this.address); byte8 = this.GetByte(++this.address);
output += $"{byte8:x2}\t{mnemomic}\t{WrapIndirect($"{byte8:x2},{r}", indirect)}"; output += $"{byte8:x2}\t{mnemomic}\t{WrapIndirect($"{byte8:x2},{r}", indirect)}";
break; break;
case 0b1001: // n,R (sixteen-bit) case 0b1001: // n,R (sixteen-bit)
word = this.GetWord(++this.address); word = this.GetWord(++this.address);
output += $"{word:x4}\t{mnemomic}\t{WrapIndirect($"{word:x4},{r}", indirect)}"; output += $"{word:x4}\t{mnemomic}\t{WrapIndirect($"{word:x4},{r}", indirect)}";
break; break;
case 0b1011: // D,R case 0b1011: // D,R
output += $"\t{mnemomic}\t{WrapIndirect($"D,{r}", indirect)}"; output += $"\t{mnemomic}\t{WrapIndirect($"D,{r}", indirect)}";
break; break;
case 0b1100: // n,PCR (eight-bit) case 0b1100: // n,PCR (eight-bit)
byte8 = this.GetByte(++this.address); byte8 = this.GetByte(++this.address);
output += $"{byte8:x2}\t{mnemomic}\t{WrapIndirect("${(byte)byte8:D},PCR", indirect)}"; output += $"{byte8:x2}\t{mnemomic}\t{WrapIndirect("${(byte)byte8:D},PCR", indirect)}";
break; break;
case 0b1101: // n,PCR (sixteen-bit) case 0b1101: // n,PCR (sixteen-bit)
word = this.GetWord(++this.address); word = this.GetWord(++this.address);
output += $"{word:x4}\t{mnemomic}\t{WrapIndirect("${(short)word:D},PCR", indirect)}"; output += $"{word:x4}\t{mnemomic}\t{WrapIndirect("${(short)word:D},PCR", indirect)}";
break; break;
case 0b1111: // [n] case 0b1111: // [n]
if (!indirect) if (!indirect)
{ {
throw new InvalidOperationException("Index specification cannot be direct"); throw new InvalidOperationException("Index specification cannot be direct");
@ -671,7 +686,7 @@
else else
{ {
// EA = ,R + 5-bit offset // 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; return output;
@ -711,44 +726,6 @@
private string BranchLong(string mnemomic) => this.Address_relative_word(mnemomic); 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) private string TFR(string mnemomic)
{ {
var data = this.GetByte(++this.address); var data = this.GetByte(++this.address);
@ -763,7 +740,7 @@
: $"{output}{ReferenceTransfer16(reg1)},{ReferenceTransfer16(reg2)}"; : $"{output}{ReferenceTransfer16(reg1)},{ReferenceTransfer16(reg2)}";
} }
// ////
private string PulS() => this.PulX("PULS", "U"); private string PulS() => this.PulX("PULS", "U");

View File

@ -40,20 +40,20 @@ namespace EightBit
{ {
if (absolute < 0x8000) 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) 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) 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() public override void RaisePOWER()

View File

@ -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; using System;
@ -6,16 +9,18 @@
// http://www.cpu-world.com/Arch/6809.html // http://www.cpu-world.com/Arch/6809.html
// http://atjs.mbnet.fi/mc6809/Information/6809.htm // http://atjs.mbnet.fi/mc6809/Information/6809.htm
// |---------------|-----------------------------------| /*
// | MPU State | | |---------------|-----------------------------------|
// |_______________| MPU State Definition | | MPU State | |
// | BA | BS | | |_______________| MPU State Definition |
// |_______|_______|___________________________________| | BA | BS | |
// | 0 | 0 | Normal (running) | |_______|_______|___________________________________|
// | 0 | 1 | Interrupt or RESET Acknowledge | | 0 | 0 | Normal (running) |
// | 1 | 0 | SYNC Acknowledge | | 0 | 1 | Interrupt or RESET Acknowledge |
// | 1 | 1 | HALT Acknowledge | | 1 | 0 | SYNC Acknowledge |
// |-------|-------|-----------------------------------| | 1 | 1 | HALT Acknowledge |
|-------|-------|-----------------------------------|
*/
public sealed class MC6809 : BigEndianProcessor public sealed class MC6809 : BigEndianProcessor
{ {
@ -26,7 +31,6 @@
private const byte FIRQvector = 0xf6; // FIRQ vector private const byte FIRQvector = 0xf6; // FIRQ vector
private const byte SWI2vector = 0xf4; // SWI2 vector private const byte SWI2vector = 0xf4; // SWI2 vector
private const byte SWI3vector = 0xf2; // SWI3 vector private const byte SWI3vector = 0xf2; // SWI3 vector
// private const byte RESERVEDvector = 0xf0; // RESERVED vector
private byte cc = 0; private byte cc = 0;
private byte dp = 0; private byte dp = 0;
@ -118,6 +122,18 @@
public bool Halted => this.HALT.Lowered(); 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 EntireRegisterSet => this.CC & (byte)StatusBits.EF;
public int FastInterruptMasked => this.CC & (byte)StatusBits.FF; public int FastInterruptMasked => this.CC & (byte)StatusBits.FF;
@ -146,18 +162,6 @@
private bool GT => !this.LE; // !(Z OR (N XOR V)) 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() public void Halt()
{ {
--this.PC.Word; --this.PC.Word;
@ -400,6 +404,16 @@
return base.BusRead(); 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() private void HandleHALT()
{ {
this.RaiseBA(); this.RaiseBA();
@ -482,16 +496,6 @@
private void OnExecutedInstruction() => this.ExecutedInstruction?.Invoke(this, EventArgs.Empty); 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 Push(Register16 stack, byte value) => this.BusWrite(--stack.Word, value);
private void PushS(byte value) => this.Push(this.S, value); private void PushS(byte value) => this.Push(this.S, value);
@ -515,7 +519,8 @@
private Register16 RR(int which) private Register16 RR(int which)
{ {
switch (which) { switch (which)
{
case 0b00: case 0b00:
return this.X; return this.X;
case 0b01: case 0b01:
@ -553,58 +558,58 @@
var address = new Register16(); var address = new Register16();
if ((type & (byte)Bits.Bit7) != 0) 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); this.Tick(2);
address.Word = r.Word++; address.Word = r.Word++;
break; break;
case 0b0001: // ,R++ case 0b0001: // ,R++
this.Tick(3); this.Tick(3);
address.Word = r.Word; address.Word = r.Word;
r.Word += 2; r.Word += 2;
break; break;
case 0b0010: // ,-R case 0b0010: // ,-R
this.Tick(2); this.Tick(2);
address.Word = --r.Word; address.Word = --r.Word;
break; break;
case 0b0011: // ,--R case 0b0011: // ,--R
this.Tick(3); this.Tick(3);
r.Word -= 2; r.Word -= 2;
address.Word = r.Word; address.Word = r.Word;
break; break;
case 0b0100: // ,R case 0b0100: // ,R
address.Word = r.Word; address.Word = r.Word;
break; break;
case 0b0101: // B,R case 0b0101: // B,R
this.Tick(); this.Tick();
address.Word = (ushort)(r.Word + (sbyte)this.B); address.Word = (ushort)(r.Word + (sbyte)this.B);
break; break;
case 0b0110: // A,R case 0b0110: // A,R
this.Tick(); this.Tick();
address.Word = (ushort)(r.Word + (sbyte)this.A); address.Word = (ushort)(r.Word + (sbyte)this.A);
break; break;
case 0b1000: // n,R (eight-bit) case 0b1000: // n,R (eight-bit)
this.Tick(); this.Tick();
address.Word = (ushort)(r.Word + (sbyte)this.FetchByte()); address.Word = (ushort)(r.Word + (sbyte)this.FetchByte());
break; break;
case 0b1001: // n,R (sixteen-bit) case 0b1001: // n,R (sixteen-bit)
this.Tick(4); this.Tick(4);
address.Word = (ushort)(r.Word + (short)this.FetchWord().Word); address.Word = (ushort)(r.Word + (short)this.FetchWord().Word);
break; break;
case 0b1011: // D,R case 0b1011: // D,R
this.Tick(4); this.Tick(4);
address.Word = (ushort)(r.Word + this.D.Word); address.Word = (ushort)(r.Word + this.D.Word);
break; break;
case 0b1100: // n,PCR (eight-bit) case 0b1100: // n,PCR (eight-bit)
this.Tick(); this.Tick();
address.Word = this.Address_relative_byte().Word; address.Word = this.Address_relative_byte().Word;
break; break;
case 0b1101: // n,PCR (sixteen-bit) case 0b1101: // n,PCR (sixteen-bit)
this.Tick(2); this.Tick(2);
address.Word = this.Address_relative_word().Word; address.Word = this.Address_relative_word().Word;
break; break;
case 0b1111: // [n] case 0b1111: // [n]
this.Tick(2); this.Tick(2);
address.Word = this.Address_extended().Word; address.Word = this.Address_extended().Word;
break; break;
@ -623,8 +628,9 @@
{ {
// EA = ,R + 5-bit offset // EA = ,R + 5-bit offset
this.Tick(); 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; return address;
} }
@ -683,7 +689,7 @@
private byte AdjustOverflow(ushort before, ushort data, uint after) 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); var highAfter = (ushort)(after >> 16);
return SetBit(this.CC, StatusBits.VF, (before ^ data ^ lowAfter ^ (highAfter << 15)) & (int)Bits.Bit15); 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) 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.AdjustNZ(result);
this.CC = this.AdjustCarry(after); this.CC = this.AdjustCarry(after);
return this.AdjustOverflow(before, data, after); return this.AdjustOverflow(before, data, after);
@ -719,7 +725,7 @@
private byte AdjustSubtraction(ushort before, ushort data, uint after) 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.AdjustNZ(result);
this.CC = this.AdjustCarry(after); this.CC = this.AdjustCarry(after);
return this.AdjustOverflow(before, data, after); return this.AdjustOverflow(before, data, after);
@ -785,9 +791,9 @@
this.SaveRegisterState(); 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) private ref byte ReferenceTransfer8(int specifier)
{ {
@ -808,7 +814,8 @@
private Register16 ReferenceTransfer16(int specifier) private Register16 ReferenceTransfer16(int specifier)
{ {
switch (specifier) { switch (specifier)
{
case 0b0000: case 0b0000:
return this.D; return this.D;
case 0b0001: case 0b0001:
@ -1166,7 +1173,6 @@
case 0x7d: this.Tick(7); this.TST(this.AM_extended_byte()); break; // TST (extended) case 0x7d: this.Tick(7); this.TST(this.AM_extended_byte()); break; // TST (extended)
// Branching // Branching
case 0x16: this.Tick(5); this.Jump(this.Address_relative_word()); break; // BRA (LBRA relative) 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 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) 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) case 0xbe: this.Tick(7); this.Y.Word = this.LD(this.AM_extended_word()).Word; break; // LD (LDY extended)
// Branching // Branching
case 0x21: this.Tick(5); this.Address_relative_word(); break; // BRN (LBRN relative) 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 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) case 0x23: this.Tick(5); this.BranchLong(this.LS); break; // BLS (LBLS relative)
@ -1300,7 +1305,7 @@
{ {
var addition = (uint)(operand.Word + data.Word); var addition = (uint)(operand.Word + data.Word);
this.CC = this.AdjustAddition(operand, data, addition); 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)); private byte AndR(byte operand, byte data) => this.Through((byte)(operand & data));
@ -1398,7 +1403,7 @@
{ {
ref var rightRegister = ref this.ReferenceTransfer8(rightSpecifier); ref var rightRegister = ref this.ReferenceTransfer8(rightSpecifier);
(leftRegister.Low, rightRegister) = (rightRegister, leftRegister.Low); (leftRegister.Low, rightRegister) = (rightRegister, leftRegister.Low);
leftRegister.High = (byte)Mask.Mask8; leftRegister.High = (byte)Mask.Eight;
} }
} }
else else
@ -1408,7 +1413,7 @@
{ {
var rightRegister = this.ReferenceTransfer16(rightSpecifier); var rightRegister = this.ReferenceTransfer16(rightSpecifier);
(leftRegister, rightRegister.Low) = (rightRegister.Low, leftRegister); (leftRegister, rightRegister.Low) = (rightRegister.Low, leftRegister);
rightRegister.High =(byte)Mask.Mask8; rightRegister.High =(byte)Mask.Eight;
} }
else else
{ {
@ -1470,6 +1475,7 @@
if ((data & (byte)Bits.Bit6) != 0) if ((data & (byte)Bits.Bit6) != 0)
{ {
this.Tick(2); this.Tick(2);
// Pushing to the S stack means we must be pushing U // Pushing to the S stack means we must be pushing U
this.PushWord(stack, object.ReferenceEquals(stack, this.S) ? this.U : this.S); this.PushWord(stack, object.ReferenceEquals(stack, this.S) ? this.U : this.S);
} }
@ -1552,6 +1558,7 @@
if ((data & (byte)Bits.Bit6) != 0) if ((data & (byte)Bits.Bit6) != 0)
{ {
this.Tick(2); this.Tick(2);
// Pulling from the S stack means we must be pulling U // 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; (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); var subtraction = (uint)(operand.Word - data.Word);
this.CC = this.AdjustSubtraction(operand, data, subtraction); 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) private byte SEX(byte from)
{ {
this.CC = this.AdjustNZ(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() private void SWI()
@ -1657,7 +1664,7 @@
{ {
var destinationRegister = this.ReferenceTransfer16(destinationSpecifier); var destinationRegister = this.ReferenceTransfer16(destinationSpecifier);
destinationRegister.Low = sourceRegister; destinationRegister.Low = sourceRegister;
destinationRegister.High = (byte)Mask.Mask8; destinationRegister.High = (byte)Mask.Eight;
} }
else else
{ {

View File

@ -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; using System;

View File

@ -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; using System;

View File

@ -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; using System;

View File

@ -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; using System;
@ -8,12 +11,12 @@
private readonly ulong[] addressProfiles; private readonly ulong[] addressProfiles;
private readonly ulong[] addressCounts; private readonly ulong[] addressCounts;
private ushort address;
private readonly Bus board; private readonly Bus board;
private readonly MC6809 processor; private readonly MC6809 processor;
private readonly Disassembler disassembler; private readonly Disassembler disassembler;
private ushort address;
public Profiler(Bus board, MC6809 processor, Disassembler disassembler) public Profiler(Bus board, MC6809 processor, Disassembler disassembler)
{ {
this.board = board; this.board = board;

View File

@ -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.CompilerServices;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;

View File

@ -284,6 +284,7 @@ namespace EightBit
specification = "IM 2"; specification = "IM 2";
break; break;
} }
break; break;
case 7: case 7:
switch (y) switch (y)

View File

@ -12,7 +12,7 @@ namespace EightBit
public RefreshRegister(byte value) public RefreshRegister(byte value)
{ {
this.high = (byte)(value & (byte)Bits.Bit7); 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); 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 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) public static RefreshRegister Increment(RefreshRegister value)
{ {

View File

@ -27,7 +27,7 @@ namespace EightBit
// Parity // Parity
PF = Bits.Bit2, PF = Bits.Bit2,
// Zero // Overflow
VF = Bits.Bit2, VF = Bits.Bit2,
// Negative? // Negative?

View File

@ -44,7 +44,7 @@ namespace Fuse
foreach (var e in result.Events.Container) foreach (var e in result.Events.Container)
{ {
// Ignore contention events // Ignore contention events
if (!e.Specifier.EndsWith("C")) if (!e.Specifier.EndsWith("C", System.StringComparison.Ordinal))
{ {
this.expectedEvents.Add(e); this.expectedEvents.Add(e);
} }
@ -55,7 +55,7 @@ namespace Fuse
public bool Unimplemented { get; private set; } = false; 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() public void Run()
{ {
@ -446,7 +446,7 @@ namespace Fuse
private static string ToString(TestEvent e) private static string ToString(TestEvent e)
{ {
var output = $"Cycles = {e.Cycles}, Specifier = {e.Specifier}, Address = {e.Address:X4}"; 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}"; output += $", Value={e.Value:X2}";
} }

View File

@ -23,7 +23,7 @@ namespace Z80.Test
this.ports = new InputOutput(); this.ports = new InputOutput();
this.CPU = new Z80(this, this.ports); this.CPU = new Z80(this, this.ports);
this.disassembler = new Disassembler(this); 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; } public Z80 CPU { get; }

View File

@ -417,12 +417,12 @@ namespace EightBit
this.IM = 0; this.IM = 0;
this.REFRESH = new RefreshRegister(0); this.REFRESH = new RefreshRegister(0);
this.IV = (byte)Mask.Mask8; this.IV = (byte)Mask.Eight;
this.ExxAF(); this.ExxAF();
this.Exx(); 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; this.prefixCB = this.prefixDD = this.prefixED = this.prefixFD = false;
@ -519,7 +519,7 @@ namespace EightBit
base.HandleRESET(); base.HandleRESET();
this.DisableInterrupts(); this.DisableInterrupts();
this.IV = this.REFRESH = 0; 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); this.Tick(3);
} }
@ -1035,6 +1035,7 @@ namespace EightBit
this.PC.Word -= 2; this.PC.Word -= 2;
this.Tick(5); this.Tick(5);
} }
this.Tick(3); this.Tick(3);
break; break;
case 7: // OTDR case 7: // OTDR
@ -1043,6 +1044,7 @@ namespace EightBit
this.PC.Word -= 2; this.PC.Word -= 2;
this.Tick(5); this.Tick(5);
} }
this.Tick(3); this.Tick(3);
break; break;
} }
@ -1200,6 +1202,7 @@ namespace EightBit
this.R(y, this.Increment(original)); this.R(y, this.Increment(original));
break; break;
} }
case 5: // 8-bit DEC case 5: // 8-bit DEC
{ {
if (memoryY && this.displaced) if (memoryY && this.displaced)
@ -1230,6 +1233,7 @@ namespace EightBit
this.R(y, value); // LD r,n this.R(y, value); // LD r,n
break; break;
} }
case 7: // Assorted operations on accumulator/flags case 7: // Assorted operations on accumulator/flags
switch (y) switch (y)
{ {
@ -1634,7 +1638,7 @@ namespace EightBit
this.F = ClearBit(this.F, StatusBits.HC, LowNibble(operand)); this.F = ClearBit(this.F, StatusBits.HC, LowNibble(operand));
var result = --operand; var result = --operand;
this.F = AdjustSZXY(this.F, result); 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; return result;
} }
@ -1697,7 +1701,7 @@ namespace EightBit
return this.intermediate.Word; 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.Add(operand, value, this.F & (byte)StatusBits.CF); // Leaves result in intermediate anyway
this.F = ClearBit(this.F, StatusBits.ZF, this.intermediate.Word); this.F = ClearBit(this.F, StatusBits.ZF, this.intermediate.Word);
@ -2049,7 +2053,7 @@ namespace EightBit
this.MEMPTR.Word = destination.Word; this.MEMPTR.Word = destination.Word;
this.F = SetBit(this.F, StatusBits.NF, value & (byte)Bits.Bit7); 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 = 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() private void OUTI()