Tidy up all the 6809 stuff

This commit is contained in:
Adrian Conlon
2025-05-12 21:08:39 +01:00
parent 6e1fc14530
commit a5eed89b26
43 changed files with 187 additions and 201 deletions

View File

@@ -1,35 +1,28 @@
// <copyright file="Disassembler.cs" company="Adrian Conlon">
// Copyright (c) Adrian Conlon. All rights reserved.
// </copyright>
namespace EightBit
namespace MC6809
{
using System;
using System.Collections.Generic;
using EightBit;
public sealed class Disassembler
public sealed class Disassembler(Bus bus, MC6809 targetProcessor)
{
private ushort address = 0xffff;
private bool prefix10 = false;
private bool prefix11 = false;
private bool prefix10;
private bool prefix11;
public Disassembler(Bus bus, MC6809 targetProcessor)
{
this.BUS = bus;
this.CPU = targetProcessor;
}
public bool Pause { get; set; } = false;
public bool Pause { get; set; }
public bool Ignore => this.CPU.HALT.Lowered()
|| this.CPU.RESET.Lowered()
|| this.CPU.NMI.Lowered()
|| (this.CPU.FIRQ.Lowered() && this.CPU.FastInterruptMasked == 0)
|| (this.CPU.INT.Lowered() && this.CPU.InterruptMasked == 0);
|| this.CPU.FIRQ.Lowered() && this.CPU.FastInterruptMasked == 0
|| this.CPU.INT.Lowered() && this.CPU.InterruptMasked == 0;
private Bus BUS { get; }
private Bus BUS { get; } = bus;
private MC6809 CPU { get; }
private MC6809 CPU { get; } = targetProcessor;
public string Trace(ushort current)
{
@@ -45,7 +38,11 @@ namespace EightBit
return $"{current:x4}|{disassembled}\t\tcc={cc:x2} a={a:x2} b={b:x2} dp={dp:x2} x={x:x4} y={y:x4} u={u:x4} s={s:x4}";
}
public string Trace(Register16 current) => this.Trace(current.Word);
public string Trace(Register16 current)
{
ArgumentNullException.ThrowIfNull(current, nameof(current));
return this.Trace(current.Word);
}
public string Trace() => this.Trace(this.CPU.PC);
@@ -67,19 +64,14 @@ namespace EightBit
private static string RR(int which)
{
switch (which)
return which switch
{
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");
}
0b00 => "X",
0b01 => "Y",
0b10 => "U",
0b11 => "S",
_ => throw new ArgumentOutOfRangeException(nameof(which), which, "Register specification is unknown"),
};
}
private static string WrapIndirect(string what, bool indirect)
@@ -91,40 +83,28 @@ namespace EightBit
private static string ReferenceTransfer8(int specifier)
{
switch (specifier)
return specifier switch
{
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");
}
0b1000 => "A",
0b1001 => "B",
0b1010 => "CC",
0b1011 => "DP",
_ => throw new ArgumentOutOfRangeException(nameof(specifier), specifier, "8bit register specification is unknown"),
};
}
private static string ReferenceTransfer16(int specifier)
{
switch (specifier)
return specifier switch
{
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");
}
0b0000 => "D",
0b0001 => "X",
0b0010 => "Y",
0b0011 => "U",
0b0100 => "S",
0b0101 => "PC",
_ => throw new ArgumentOutOfRangeException(nameof(specifier), specifier, "16bit register specification is unknown"),
};
}
private string Disassemble(int current) => this.Disassemble((ushort)current);
@@ -609,66 +589,64 @@ namespace EightBit
////
private string Address_direct(string mnemomic)
private string Address_direct(string mnemonic)
{
var offset = this.GetByte(++this.address);
return $"{offset:x2}\t{mnemomic}\t${offset:x2}";
return $"{offset:x2}\t{mnemonic}\t${offset:x2}";
}
private string Address_indexed(string mnemomic)
private string Address_indexed(string mnemonic)
{
var type = this.GetByte(++this.address);
var r = RR((type & (byte)(Bits.Bit6 | Bits.Bit5)) >> 5);
byte byte8 = 0xff;
ushort word = 0xffff;
var output = $"{type:x2}";
if ((type & (byte)Bits.Bit7) != 0)
{
var indirect = (type & (byte)Bits.Bit4) != 0;
ushort word;
byte byte8;
switch (type & (byte)Mask.Four)
{
case 0b0000: // ,R+
output += $"\t{mnemomic}\t{WrapIndirect($",{r}+", indirect)}";
output += $"\t{mnemonic}\t{WrapIndirect($",{r}+", indirect)}";
break;
case 0b0001: // ,R++
output += $"\t{mnemomic}\t{WrapIndirect($",{r}++", indirect)}";
output += $"\t{mnemonic}\t{WrapIndirect($",{r}++", indirect)}";
break;
case 0b0010: // ,-R
output += $"\t{mnemomic}\t{WrapIndirect($",-{r}", indirect)}";
output += $"\t{mnemonic}\t{WrapIndirect($",-{r}", indirect)}";
break;
case 0b0011: // ,--R
output += $"\t{mnemomic}\t{WrapIndirect($",--{r}", indirect)}";
output += $"\t{mnemonic}\t{WrapIndirect($",--{r}", indirect)}";
break;
case 0b0100: // ,R
output += $"\t{mnemomic}\t{WrapIndirect($",{r}", indirect)}";
output += $"\t{mnemonic}\t{WrapIndirect($",{r}", indirect)}";
break;
case 0b0101: // B,R
output += $"\t{mnemomic}\t{WrapIndirect($"B,{r}", indirect)}";
output += $"\t{mnemonic}\t{WrapIndirect($"B,{r}", indirect)}";
break;
case 0b0110: // A,R
output += $"\t{mnemomic}\t{WrapIndirect($"A,{r}", indirect)}";
output += $"\t{mnemonic}\t{WrapIndirect($"A,{r}", indirect)}";
break;
case 0b1000: // n,R (eight-bit)
byte8 = this.GetByte(++this.address);
output += $"{byte8:x2}\t{mnemomic}\t{WrapIndirect($"{byte8:x2},{r}", indirect)}";
output += $"{byte8:x2}\t{mnemonic}\t{WrapIndirect($"{byte8:x2},{r}", indirect)}";
break;
case 0b1001: // n,R (sixteen-bit)
word = this.GetWord(++this.address);
output += $"{word:x4}\t{mnemomic}\t{WrapIndirect($"{word:x4},{r}", indirect)}";
output += $"{word:x4}\t{mnemonic}\t{WrapIndirect($"{word:x4},{r}", indirect)}";
break;
case 0b1011: // D,R
output += $"\t{mnemomic}\t{WrapIndirect($"D,{r}", indirect)}";
output += $"\t{mnemonic}\t{WrapIndirect($"D,{r}", indirect)}";
break;
case 0b1100: // n,PCR (eight-bit)
byte8 = this.GetByte(++this.address);
output += $"{byte8:x2}\t{mnemomic}\t{WrapIndirect("${(byte)byte8:D},PCR", indirect)}";
output += $"{byte8:x2}\t{mnemonic}\t{WrapIndirect("${(byte)byte8:D},PCR", indirect)}";
break;
case 0b1101: // n,PCR (sixteen-bit)
word = this.GetWord(++this.address);
output += $"{word:x4}\t{mnemomic}\t{WrapIndirect("${(short)word:D},PCR", indirect)}";
output += $"{word:x4}\t{mnemonic}\t{WrapIndirect("${(short)word:D},PCR", indirect)}";
break;
case 0b1111: // [n]
if (!indirect)
@@ -677,7 +655,7 @@ namespace EightBit
}
word = this.GetWord(++this.address);
output += $"{word:x4}\t{mnemomic}\t{WrapIndirect("${word:x4}", indirect)}";
output += $"{word:x4}\t{mnemonic}\t{WrapIndirect("${word:x4}", indirect)}";
break;
default:
throw new InvalidOperationException("Invalid index specification used");
@@ -686,53 +664,53 @@ namespace EightBit
else
{
// EA = ,R + 5-bit offset
output += $"\t{mnemomic}\t{Processor.SignExtend(5, type & (byte)Mask.Five)},{r}";
output += $"\t{mnemonic}\t{Processor.SignExtend(5, type & (byte)Mask.Five)},{r}";
}
return output;
}
private string Address_extended(string mnemomic)
private string Address_extended(string mnemonic)
{
var word = this.GetWord(++this.address);
return $"{word:x4}\t{mnemomic}\t${word:x4}";
return $"{word:x4}\t{mnemonic}\t${word:x4}";
}
private string Address_relative_byte(string mnemomic)
private string Address_relative_byte(string mnemonic)
{
var byte8 = this.GetByte(++this.address);
return $"{byte8:x2}\t{mnemomic}\t${++this.address + (sbyte)byte8:x4}";
return $"{byte8:x2}\t{mnemonic}\t${++this.address + (sbyte)byte8:x4}";
}
private string Address_relative_word(string mnemomic)
private string Address_relative_word(string mnemonic)
{
var word = this.GetWord(++this.address);
return $"{word:x4}\t{mnemomic}\t${++this.address + (short)word:x4}";
return $"{word:x4}\t{mnemonic}\t${++this.address + (short)word:x4}";
}
private string AM_immediate_byte(string mnemomic)
private string AM_immediate_byte(string mnemonic)
{
var byte8 = this.GetByte(++this.address);
return $"{byte8:x2}\t{mnemomic}\t#${byte8:x2}";
return $"{byte8:x2}\t{mnemonic}\t#${byte8:x2}";
}
private string AM_immediate_word(string mnemomic)
private string AM_immediate_word(string mnemonic)
{
var word = this.GetWord(++this.address);
return $"{word:x4}\t{mnemomic}\t#${word:x4}";
return $"{word:x4}\t{mnemonic}\t#${word:x4}";
}
private string BranchShort(string mnemomic) => this.Address_relative_byte(mnemomic);
private string BranchShort(string mnemonic) => this.Address_relative_byte(mnemonic);
private string BranchLong(string mnemomic) => this.Address_relative_word(mnemomic);
private string BranchLong(string mnemonic) => this.Address_relative_word(mnemonic);
private string TFR(string mnemomic)
private string TFR(string mnemonic)
{
var data = this.GetByte(++this.address);
var reg1 = Chip.HighNibble(data);
var reg2 = Chip.LowNibble(data);
var output = $"{data:x2}\t{mnemomic}\t";
var output = $"{data:x2}\t{mnemonic}\t";
var type8 = (reg1 & (byte)Bits.Bit3) != 0; // 8 bit?
return type8
@@ -750,10 +728,10 @@ namespace EightBit
private string PshU() => this.PshX("PSHU", "S");
private string PulX(string mnemomic, string upon)
private string PulX(string mnemonic, string upon)
{
var data = this.GetByte(++this.address);
var output = $"{data:x2}\t{mnemomic}\t";
var output = $"{data:x2}\t{mnemonic}\t";
var registers = new List<string>();
if ((data & (byte)Bits.Bit0) != 0)
@@ -799,10 +777,10 @@ namespace EightBit
return output + string.Join(",", registers);
}
private string PshX(string mnemomic, string upon)
private string PshX(string mnemonic, string upon)
{
var data = this.GetByte(++this.address);
var output = $"{data:x2}\t{mnemomic}\t";
var output = $"{data:x2}\t{mnemonic}\t";
var registers = new List<string>();
if ((data & (byte)Bits.Bit7) != 0)

View File

@@ -4,6 +4,7 @@
namespace EightBit
{
using MC6809;
using Microsoft.VisualStudio.TestTools.UnitTesting;
[TestClass]

View File

@@ -4,6 +4,7 @@
namespace EightBit
{
using MC6809;
using Microsoft.VisualStudio.TestTools.UnitTesting;
[TestClass]

View File

@@ -4,6 +4,7 @@
namespace EightBit
{
using MC6809;
using Microsoft.VisualStudio.TestTools.UnitTesting;
[TestClass]

View File

@@ -4,6 +4,7 @@
namespace EightBit
{
using MC6809;
using Microsoft.VisualStudio.TestTools.UnitTesting;
[TestClass]

View File

@@ -4,6 +4,7 @@
namespace EightBit
{
using MC6809;
using Microsoft.VisualStudio.TestTools.UnitTesting;
[TestClass]

View File

@@ -4,6 +4,7 @@
namespace EightBit
{
using MC6809;
using Microsoft.VisualStudio.TestTools.UnitTesting;
[TestClass]

View File

@@ -4,6 +4,7 @@
namespace EightBit
{
using MC6809;
using Microsoft.VisualStudio.TestTools.UnitTesting;
[TestClass]

View File

@@ -4,6 +4,7 @@
namespace EightBit
{
using MC6809;
using Microsoft.VisualStudio.TestTools.UnitTesting;
[TestClass]

View File

@@ -4,6 +4,7 @@
namespace EightBit
{
using MC6809;
using Microsoft.VisualStudio.TestTools.UnitTesting;
[TestClass]

View File

@@ -4,6 +4,7 @@
namespace EightBit
{
using MC6809;
using Microsoft.VisualStudio.TestTools.UnitTesting;
[TestClass]

View File

@@ -4,6 +4,8 @@
namespace EightBit
{
using MC6809;
public sealed class Board : EightBit.Bus
{
private readonly Ram ram = new Ram(0x10000); // 0000 - FFFF, 64K RAM

View File

@@ -4,6 +4,7 @@
namespace EightBit
{
using MC6809;
using Microsoft.VisualStudio.TestTools.UnitTesting;
[TestClass]

View File

@@ -4,6 +4,7 @@
namespace EightBit
{
using MC6809;
using Microsoft.VisualStudio.TestTools.UnitTesting;
[TestClass]

View File

@@ -4,6 +4,7 @@
namespace EightBit
{
using MC6809;
using Microsoft.VisualStudio.TestTools.UnitTesting;
[TestClass]

View File

@@ -4,6 +4,7 @@
namespace EightBit
{
using MC6809;
using Microsoft.VisualStudio.TestTools.UnitTesting;
[TestClass]

View File

@@ -4,6 +4,7 @@
namespace EightBit
{
using MC6809;
using Microsoft.VisualStudio.TestTools.UnitTesting;
[TestClass]

View File

@@ -4,6 +4,7 @@
namespace EightBit
{
using MC6809;
using Microsoft.VisualStudio.TestTools.UnitTesting;
[TestClass]

View File

@@ -4,6 +4,7 @@
namespace EightBit
{
using MC6809;
using Microsoft.VisualStudio.TestTools.UnitTesting;
[TestClass]

View File

@@ -4,6 +4,7 @@
namespace EightBit
{
using MC6809;
using Microsoft.VisualStudio.TestTools.UnitTesting;
[TestClass]

View File

@@ -4,6 +4,7 @@
namespace EightBit
{
using MC6809;
using Microsoft.VisualStudio.TestTools.UnitTesting;
// https://github.com/sorenroug/osnine-java/blob/master/core/src/test/java/org/roug/osnine/BranchAndJumpTest.java

View File

@@ -4,6 +4,7 @@
namespace EightBit
{
using MC6809;
using Microsoft.VisualStudio.TestTools.UnitTesting;
[TestClass]

View File

@@ -4,6 +4,7 @@
namespace EightBit
{
using MC6809;
using Microsoft.VisualStudio.TestTools.UnitTesting;
[TestClass]

View File

@@ -4,6 +4,7 @@
namespace EightBit
{
using MC6809;
using Microsoft.VisualStudio.TestTools.UnitTesting;
[TestClass]
@@ -46,9 +47,9 @@ namespace EightBit
public void TestLSR_a_two()
{
this.board.Poke(0xb00, 0x44);
this.cpu.CC &= (byte)~StatusBits.CF;
this.cpu.CC |= (byte)StatusBits.VF;
this.cpu.CC |= (byte)StatusBits.NF;
this.cpu.CC = MC6809.ClearBit(this.cpu.CC, (byte)StatusBits.CF);
this.cpu.CC = MC6809.SetBit(this.cpu.CC, (byte)StatusBits.VF);
this.cpu.CC = MC6809.SetBit(this.cpu.CC, (byte)StatusBits.NF);
this.cpu.A = 1;
this.cpu.PC.Word = 0xb00;
@@ -65,8 +66,8 @@ namespace EightBit
public void TestLSR_a_three()
{
this.board.Poke(0xb00, 0x44);
this.cpu.CC &= (byte)~StatusBits.CF;
this.cpu.CC &= (byte)~StatusBits.VF;
this.cpu.CC = MC6809.ClearBit(this.cpu.CC, (byte)StatusBits.CF);
this.cpu.CC = MC6809.ClearBit(this.cpu.CC, (byte)StatusBits.VF);
this.cpu.A = 0xb8;
this.cpu.PC.Word = 0xb00;

View File

@@ -4,6 +4,7 @@
namespace EightBit
{
using MC6809;
using Microsoft.VisualStudio.TestTools.UnitTesting;
[TestClass]
@@ -54,8 +55,8 @@ namespace EightBit
{
this.board.Poke(0xb00, 0x3d);
this.cpu.CC = 0;
this.cpu.CC &= (byte)~StatusBits.CF;
this.cpu.CC |= (byte)StatusBits.ZF;
this.cpu.CC = MC6809.ClearBit(this.cpu.CC, (byte)StatusBits.CF);
this.cpu.CC = MC6809.SetBit(this.cpu.CC, (byte)StatusBits.ZF);
this.cpu.A = 0xc;
this.cpu.B = 0x00;
this.cpu.PC.Word = 0xb00;

View File

@@ -4,6 +4,7 @@
namespace EightBit
{
using MC6809;
using Microsoft.VisualStudio.TestTools.UnitTesting;
[TestClass]

View File

@@ -4,6 +4,7 @@
namespace EightBit
{
using MC6809;
using Microsoft.VisualStudio.TestTools.UnitTesting;
[TestClass]

View File

@@ -4,6 +4,7 @@
namespace EightBit
{
using MC6809;
using Microsoft.VisualStudio.TestTools.UnitTesting;
[TestClass]

View File

@@ -4,6 +4,7 @@
namespace EightBit
{
using MC6809;
using Microsoft.VisualStudio.TestTools.UnitTesting;
[TestClass]

View File

@@ -4,6 +4,7 @@
namespace EightBit
{
using MC6809;
using Microsoft.VisualStudio.TestTools.UnitTesting;
[TestClass]

View File

@@ -4,6 +4,7 @@
namespace EightBit
{
using MC6809;
using Microsoft.VisualStudio.TestTools.UnitTesting;
[TestClass]
@@ -47,7 +48,7 @@ namespace EightBit
this.board.Poke(0xb00, 0x56);
this.cpu.B = 0x89;
this.cpu.CC = 0;
this.cpu.CC &= (byte)~StatusBits.CF;
this.cpu.CC = MC6809.ClearBit(this.cpu.CC, (byte)StatusBits.CF);
this.cpu.PC.Word = 0xb00;
this.cpu.Step();

View File

@@ -4,6 +4,7 @@
namespace EightBit
{
using MC6809;
using Microsoft.VisualStudio.TestTools.UnitTesting;
// https://github.com/sorenroug/osnine-java/blob/master/core/src/test/java/org/roug/osnine/BranchAndJumpTest.java

View File

@@ -4,6 +4,7 @@
namespace EightBit
{
using MC6809;
using Microsoft.VisualStudio.TestTools.UnitTesting;
[TestClass]

View File

@@ -4,6 +4,7 @@
namespace EightBit
{
using MC6809;
using Microsoft.VisualStudio.TestTools.UnitTesting;
[TestClass]

View File

@@ -4,6 +4,7 @@
namespace EightBit
{
using MC6809;
using Microsoft.VisualStudio.TestTools.UnitTesting;
[TestClass]

View File

@@ -4,6 +4,7 @@
namespace EightBit
{
using MC6809;
using Microsoft.VisualStudio.TestTools.UnitTesting;
[TestClass]

View File

@@ -4,6 +4,7 @@
namespace EightBit
{
using MC6809;
using Microsoft.VisualStudio.TestTools.UnitTesting;
[TestClass]

View File

@@ -1,8 +1,10 @@
// <copyright file="MC6809.cs" company="Adrian Conlon">
// Copyright (c) Adrian Conlon. All rights reserved.
// </copyright>
namespace EightBit
namespace MC6809
{
using EightBit;
// Uses some information from:
// http://www.cpu-world.com/Arch/6809.html
// http://atjs.mbnet.fi/mc6809/Information/6809.htm
@@ -73,6 +75,7 @@ namespace EightBit
private void OnLoweredNMI() => this.LoweredNMI?.Invoke(this, EventArgs.Empty);
[System.Diagnostics.CodeAnalysis.SuppressMessage("Design", "CA1030:Use events where appropriate", Justification = "The word 'raise' is used in an electrical sense")]
public void RaiseNMI()
{
if (this.NMI.Lowered())
@@ -117,6 +120,7 @@ namespace EightBit
private void OnLoweredFIRQ() => this.LoweredFIRQ?.Invoke(this, EventArgs.Empty);
[System.Diagnostics.CodeAnalysis.SuppressMessage("Design", "CA1030:Use events where appropriate", Justification = "The word 'raise' is used in an electrical sense")]
public void RaiseFIRQ()
{
if (this.FIRQ.Lowered())
@@ -163,6 +167,7 @@ namespace EightBit
private void OnLoweredHALT() => this.LoweredHALT?.Invoke(this, EventArgs.Empty);
[System.Diagnostics.CodeAnalysis.SuppressMessage("Design", "CA1030:Use events where appropriate", Justification = "The word 'raise' is used in an electrical sense")]
public void RaiseHALT()
{
if (this.HALT.Lowered())
@@ -219,6 +224,7 @@ namespace EightBit
private void OnLoweredBA() => this.LoweredBA?.Invoke(this, EventArgs.Empty);
[System.Diagnostics.CodeAnalysis.SuppressMessage("Design", "CA1030:Use events where appropriate", Justification = "The word 'raise' is used in an electrical sense")]
public void RaiseBA()
{
if (this.BA.Lowered())
@@ -261,6 +267,7 @@ namespace EightBit
private void OnLoweredBS() => this.LoweredBS?.Invoke(this, EventArgs.Empty);
[System.Diagnostics.CodeAnalysis.SuppressMessage("Design", "CA1030:Use events where appropriate", Justification = "The word 'raise' is used in an electrical sense")]
public void RaiseBS()
{
if (this.BS.Lowered())
@@ -305,6 +312,7 @@ namespace EightBit
private void OnLoweredRW() => this.LoweredRW?.Invoke(this, EventArgs.Empty);
[System.Diagnostics.CodeAnalysis.SuppressMessage("Design", "CA1030:Use events where appropriate", Justification = "The word 'raise' is used in an electrical sense")]
public void RaiseRW()
{
if (this.RW.Lowered())
@@ -369,15 +377,15 @@ namespace EightBit
public int Carry => this.CC & (byte)StatusBits.CF;
private bool LS => (this.Carry != 0) || (this.Zero != 0); // (C OR Z)
private bool LS => this.Carry != 0 || this.Zero != 0; // (C OR Z)
private bool HI => !this.LS; // !(C OR Z)
private bool LT => ((this.Negative >> 3) ^ (this.Overflow >> 1)) != 0; // (N XOR V)
private bool LT => (this.Negative >> 3 ^ this.Overflow >> 1) != 0; // (N XOR V)
private bool GE => !this.LT; // !(N XOR V)
private bool LE => (this.Zero != 0) || this.LT; // (Z OR (N XOR V))
private bool LE => this.Zero != 0 || this.LT; // (Z OR (N XOR V))
private bool GT => !this.LE; // !(Z OR (N XOR V))
@@ -425,14 +433,14 @@ namespace EightBit
{
var lowAfter = after.Low;
var highAfter = after.High;
return SetBit(this.CC, StatusBits.VF, (before ^ data ^ lowAfter ^ (highAfter << 7)) & (int)Bits.Bit7);
return SetBit(this.CC, StatusBits.VF, (before ^ data ^ lowAfter ^ highAfter << 7) & (int)Bits.Bit7);
}
private byte AdjustOverflow(ushort before, ushort data, uint after)
{
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);
return SetBit(this.CC, StatusBits.VF, (before ^ data ^ lowAfter ^ highAfter << 15) & (int)Bits.Bit15);
}
private byte AdjustHalfCarry(byte before, byte data, byte after) => SetBit(this.CC, StatusBits.HF, (before ^ data ^ after) & (int)Bits.Bit4);
@@ -614,19 +622,14 @@ namespace EightBit
private Register16 RR(int which)
{
switch (which)
return which switch
{
case 0b00:
return this.X;
case 0b01:
return this.Y;
case 0b10:
return this.U;
case 0b11:
return this.S;
default:
throw new ArgumentOutOfRangeException(nameof(which), which, "Which does not specify a valid register");
}
0b00 => this.X,
0b01 => this.Y,
0b10 => this.U,
0b11 => this.S,
_ => throw new ArgumentOutOfRangeException(nameof(which), which, "Which does not specify a valid register"),
};
}
private Register16 Address_indexed()
@@ -811,7 +814,7 @@ namespace EightBit
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);
this.PushWord(stack, ReferenceEquals(stack, this.S) ? this.U : this.S);
}
if ((data & (byte)Bits.Bit5) != 0)
@@ -894,7 +897,7 @@ namespace EightBit
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;
(ReferenceEquals(stack, this.S) ? this.U : this.S).Word = this.PopWord(stack).Word;
}
if ((data & (byte)Bits.Bit7) != 0)
@@ -941,10 +944,10 @@ namespace EightBit
private void EXG(byte data)
{
var leftSpecifier = Chip.HighNibble(data);
var leftSpecifier = HighNibble(data);
var leftType = leftSpecifier & (int)Bits.Bit3;
var rightSpecifier = Chip.LowNibble(data);
var rightSpecifier = LowNibble(data);
var rightType = rightSpecifier & (int)Bits.Bit3;
if (leftType == 0)
@@ -981,10 +984,10 @@ namespace EightBit
private void TFR(byte data)
{
var sourceSpecifier = Chip.HighNibble(data);
var sourceSpecifier = HighNibble(data);
var sourceType = sourceSpecifier & (int)Bits.Bit3;
var destinationSpecifier = Chip.LowNibble(data);
var destinationSpecifier = LowNibble(data);
var destinationType = destinationSpecifier & (int)Bits.Bit3;
if (sourceType == 0)
@@ -1037,11 +1040,11 @@ namespace EightBit
{
this.HandleNMI();
}
else if (this.FIRQ.Lowered() && (this.FastInterruptMasked == 0))
else if (this.FIRQ.Lowered() && this.FastInterruptMasked == 0)
{
this.HandleFIRQ();
}
else if (this.INT.Lowered() && (this.InterruptMasked == 0))
else if (this.INT.Lowered() && this.InterruptMasked == 0)
{
this.HandleINT();
}
@@ -1558,7 +1561,7 @@ namespace EightBit
{
this.CC = SetBit(this.CC, StatusBits.CF, operand & (byte)Bits.Bit7);
this.CC = this.AdjustNZ(operand <<= 1);
var overflow = this.Carry ^ (this.Negative >> 3);
var overflow = this.Carry ^ this.Negative >> 3;
this.CC = SetBit(this.CC, StatusBits.VF, overflow);
return operand;
}
@@ -1566,7 +1569,7 @@ namespace EightBit
private byte ASR(byte operand)
{
this.CC = SetBit(this.CC, StatusBits.CF, operand & (byte)Bits.Bit0);
var result = (byte)((operand >> 1) | (int)Bits.Bit7);
var result = (byte)(operand >> 1 | (int)Bits.Bit7);
this.CC = this.AdjustNZ(result);
return result;
}
@@ -1600,8 +1603,8 @@ namespace EightBit
{
this.CC = SetBit(this.CC, StatusBits.CF, operand > 0x99);
var lowAdjust = (this.HalfCarry != 0) || (Chip.LowNibble(operand) > 9);
var highAdjust = (this.Carry != 0) || (operand > 0x99);
var lowAdjust = this.HalfCarry != 0 || LowNibble(operand) > 9;
var highAdjust = this.Carry != 0 || operand > 0x99;
if (lowAdjust)
{
@@ -1670,8 +1673,8 @@ namespace EightBit
{
var carryIn = this.Carry;
this.CC = SetBit(this.CC, StatusBits.CF, operand & (byte)Bits.Bit7);
this.CC = SetBit(this.CC, StatusBits.VF, ((operand & (byte)Bits.Bit7) >> 7) ^ ((operand & (byte)Bits.Bit6) >> 6));
var result = (byte)((operand << 1) | carryIn);
this.CC = SetBit(this.CC, StatusBits.VF, (operand & (byte)Bits.Bit7) >> 7 ^ (operand & (byte)Bits.Bit6) >> 6);
var result = (byte)(operand << 1 | carryIn);
this.CC = this.AdjustNZ(result);
return result;
}
@@ -1680,7 +1683,7 @@ namespace EightBit
{
var carryIn = this.Carry;
this.CC = SetBit(this.CC, StatusBits.CF, operand & (byte)Bits.Bit0);
var result = (byte)((operand >> 1) | (carryIn << 7));
var result = (byte)(operand >> 1 | carryIn << 7);
this.CC = this.AdjustNZ(result);
return result;
}

View File

@@ -1,14 +1,10 @@
// <copyright file="ProfileEventArgs.cs" company="Adrian Conlon">
// Copyright (c) Adrian Conlon. All rights reserved.
// </copyright>
namespace EightBit
namespace MC6809
{
using System;
public class ProfileEventArgs : EventArgs
public class ProfileEventArgs(string output) : EventArgs
{
public ProfileEventArgs(string output) => this.Output = output;
public string Output { get; }
public string Output { get; } = output;
}
}

View File

@@ -1,20 +1,12 @@
// <copyright file="ProfileLineEventArgs.cs" company="Adrian Conlon">
// Copyright (c) Adrian Conlon. All rights reserved.
// </copyright>
namespace EightBit
namespace MC6809
{
using System;
public class ProfileLineEventArgs : EventArgs
public class ProfileLineEventArgs(string source, ulong cycles) : EventArgs
{
public ProfileLineEventArgs(string source, ulong cycles)
{
this.Source = source;
this.Cycles = cycles;
}
public string Source { get; } = source;
public string Source { get; }
public ulong Cycles { get; }
public ulong Cycles { get; } = cycles;
}
}

View File

@@ -1,23 +1,14 @@
// <copyright file="ProfileScopeEventArgs.cs" company="Adrian Conlon">
// Copyright (c) Adrian Conlon. All rights reserved.
// </copyright>
namespace EightBit
namespace MC6809
{
using System;
public class ProfileScopeEventArgs : EventArgs
public class ProfileScopeEventArgs(string scope, ulong cycles, ulong count) : EventArgs
{
public ProfileScopeEventArgs(string scope, ulong cycles, ulong count)
{
this.Scope = scope;
this.Cycles = cycles;
this.Count = count;
}
public string Scope { get; } = scope;
public string Scope { get; }
public ulong Cycles { get; } = cycles;
public ulong Cycles { get; }
public ulong Count { get; }
public ulong Count { get; } = count;
}
}

View File

@@ -1,42 +1,31 @@
// <copyright file="Profiler.cs" company="Adrian Conlon">
// Copyright (c) Adrian Conlon. All rights reserved.
// </copyright>
namespace EightBit
namespace MC6809
{
using System;
using EightBit;
public sealed class Profiler
public sealed class Profiler(Bus board, MC6809 processor, Disassembler disassembler)
{
private readonly ulong[] instructionCounts;
private readonly ulong[] addressProfiles;
private readonly ulong[] addressCounts;
private readonly ulong[] instructionCounts = new ulong[0x10000];
private readonly ulong[] addressProfiles = new ulong[0x10000];
private readonly ulong[] addressCounts = new ulong[0x10000];
private readonly Bus board;
private readonly MC6809 processor;
private readonly Disassembler disassembler;
private readonly Bus board = board;
private readonly MC6809 processor = processor;
private readonly Disassembler disassembler = disassembler;
private ushort address;
public Profiler(Bus board, MC6809 processor, Disassembler disassembler)
{
this.board = board;
this.processor = processor;
this.disassembler = disassembler;
public event EventHandler<EventArgs>? StartingOutput;
this.instructionCounts = new ulong[0x10000];
this.addressProfiles = new ulong[0x10000];
this.addressCounts = new ulong[0x10000];
}
public event EventHandler<EventArgs>? FinishedOutput;
public event EventHandler<EventArgs> StartingOutput;
public event EventHandler<EventArgs>? StartingLineOutput;
public event EventHandler<EventArgs> FinishedOutput;
public event EventHandler<EventArgs>? FinishedLineOutput;
public event EventHandler<EventArgs> StartingLineOutput;
public event EventHandler<EventArgs> FinishedLineOutput;
public event EventHandler<ProfileLineEventArgs> EmitLine;
public event EventHandler<ProfileLineEventArgs>? EmitLine;
public void Enable()
{
@@ -84,9 +73,9 @@ namespace EightBit
}
}
private void Processor_ExecutingInstruction(object sender, EventArgs e) => this.address = this.processor.PC.Word;
private void Processor_ExecutingInstruction(object? sender, EventArgs e) => this.address = this.processor.PC.Word;
private void Processor_ExecutedInstruction(object sender, EventArgs e)
private void Processor_ExecutedInstruction(object? sender, EventArgs e)
{
ushort opcode = this.board.Peek(this.address);
if (opcode == 0x10 || opcode == 0x11)

View File

@@ -2,12 +2,12 @@
// Copyright (c) Adrian Conlon. All rights reserved.
// </copyright>
namespace EightBit
namespace MC6809
{
using System;
using EightBit;
[Flags]
public enum StatusBits : byte
public enum StatusBits
{
None = 0,