mirror of
https://github.com/MoleskiCoder/EightBitNet.git
synced 2026-03-11 05:41:49 +00:00
Tidy up all the 6809 stuff
This commit is contained in:
@@ -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)
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
|
||||
namespace EightBit
|
||||
{
|
||||
using MC6809;
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
|
||||
[TestClass]
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
|
||||
namespace EightBit
|
||||
{
|
||||
using MC6809;
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
|
||||
[TestClass]
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
|
||||
namespace EightBit
|
||||
{
|
||||
using MC6809;
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
|
||||
[TestClass]
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
|
||||
namespace EightBit
|
||||
{
|
||||
using MC6809;
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
|
||||
[TestClass]
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
|
||||
namespace EightBit
|
||||
{
|
||||
using MC6809;
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
|
||||
[TestClass]
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
|
||||
namespace EightBit
|
||||
{
|
||||
using MC6809;
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
|
||||
[TestClass]
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
|
||||
namespace EightBit
|
||||
{
|
||||
using MC6809;
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
|
||||
[TestClass]
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
|
||||
namespace EightBit
|
||||
{
|
||||
using MC6809;
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
|
||||
[TestClass]
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
|
||||
namespace EightBit
|
||||
{
|
||||
using MC6809;
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
|
||||
[TestClass]
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
|
||||
namespace EightBit
|
||||
{
|
||||
using MC6809;
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
|
||||
[TestClass]
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
|
||||
namespace EightBit
|
||||
{
|
||||
using MC6809;
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
|
||||
[TestClass]
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
|
||||
namespace EightBit
|
||||
{
|
||||
using MC6809;
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
|
||||
[TestClass]
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
|
||||
namespace EightBit
|
||||
{
|
||||
using MC6809;
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
|
||||
[TestClass]
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
|
||||
namespace EightBit
|
||||
{
|
||||
using MC6809;
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
|
||||
[TestClass]
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
|
||||
namespace EightBit
|
||||
{
|
||||
using MC6809;
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
|
||||
[TestClass]
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
|
||||
namespace EightBit
|
||||
{
|
||||
using MC6809;
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
|
||||
[TestClass]
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
|
||||
namespace EightBit
|
||||
{
|
||||
using MC6809;
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
|
||||
[TestClass]
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
|
||||
namespace EightBit
|
||||
{
|
||||
using MC6809;
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
|
||||
[TestClass]
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
|
||||
namespace EightBit
|
||||
{
|
||||
using MC6809;
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
|
||||
[TestClass]
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
|
||||
namespace EightBit
|
||||
{
|
||||
using MC6809;
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
|
||||
[TestClass]
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
|
||||
namespace EightBit
|
||||
{
|
||||
using MC6809;
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
|
||||
[TestClass]
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
|
||||
namespace EightBit
|
||||
{
|
||||
using MC6809;
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
|
||||
[TestClass]
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
|
||||
namespace EightBit
|
||||
{
|
||||
using MC6809;
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
|
||||
[TestClass]
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
|
||||
namespace EightBit
|
||||
{
|
||||
using MC6809;
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
|
||||
[TestClass]
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
|
||||
namespace EightBit
|
||||
{
|
||||
using MC6809;
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
|
||||
[TestClass]
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
|
||||
namespace EightBit
|
||||
{
|
||||
using MC6809;
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
|
||||
[TestClass]
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
|
||||
namespace EightBit
|
||||
{
|
||||
using MC6809;
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
|
||||
[TestClass]
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
|
||||
namespace EightBit
|
||||
{
|
||||
using MC6809;
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
|
||||
[TestClass]
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
|
||||
namespace EightBit
|
||||
{
|
||||
using MC6809;
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
|
||||
[TestClass]
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
|
||||
namespace EightBit
|
||||
{
|
||||
using MC6809;
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
|
||||
[TestClass]
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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)
|
||||
|
||||
@@ -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,
|
||||
|
||||
|
||||
Reference in New Issue
Block a user