diff --git a/BizHawk.Emulation.Cores/BizHawk.Emulation.Cores.csproj b/BizHawk.Emulation.Cores/BizHawk.Emulation.Cores.csproj
index ef1d8c3a49..7ff964b5fb 100644
--- a/BizHawk.Emulation.Cores/BizHawk.Emulation.Cores.csproj
+++ b/BizHawk.Emulation.Cores/BizHawk.Emulation.Cores.csproj
@@ -1543,6 +1543,14 @@
+
+
+
+
+
+
+
+
diff --git a/BizHawk.Emulation.Cores/CPUs/MC6800/Disassembler.cs b/BizHawk.Emulation.Cores/CPUs/MC6800/Disassembler.cs
new file mode 100644
index 0000000000..a276eb209e
--- /dev/null
+++ b/BizHawk.Emulation.Cores/CPUs/MC6800/Disassembler.cs
@@ -0,0 +1,502 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace BizHawk.Emulation.Common.Components.MC6800
+{
+ public sealed partial class MC6800
+ {
+ static string[] table =
+ {
+ "NEG DP+i8", // 00
+ "???", // 01
+ "???", // 02
+ "COM DP+i8", // 03
+ "LSR DP+i8", // 04
+ "???", // 05
+ "ROR DP+i8", // 06
+ "ASR DP+i8", // 07
+ "ASL DP+i8", // 08
+ "ROL DP+i8", // 09
+ "DEC DP+i8", // 0a
+ "???", // 0b
+ "INC DP+i8", // 0c
+ "TST DP+i8", // 0d
+ "JMP DP+i8", // 0e
+ "CLR DP+i8", // 0f
+ "PAGE 2", // 10
+ "PAGE 3", // 11
+ "NOP", // 12
+ "SYNC", // 13
+ "???", // 14
+ "???", // 15
+ "LBRA i16", // 16
+ "LBSR i16", // 17
+ "???", // 18
+ "DAA", // 19
+ "ORCC i8", // 1a
+ "???", // 1b
+ "ANDCC i8", // 1c
+ "SEX", // 1d
+ "EXG i8", // 1e
+ "TFR i8", // 1f
+ "BRA i8", // 20
+ "BRN i8", // 21
+ "BHI i8", // 22
+ "BLS i8", // 23
+ "BHS i8", // 24
+ "BLO i8", // 25
+ "BNE i8", // 26
+ "BEQ i8", // 27
+ "BVC i8", // 28
+ "BVS i8", // 29
+ "BPL i8", // 2a
+ "BMI i8", // 2b
+ "BGE i8", // 2c
+ "BLT i8", // 2d
+ "BGT i8", // 2e
+ "BLE i8", // 2f
+ "LEAX ix16", // 30
+ "LEAY ix16", // 31
+ "LEAS ix16", // 32
+ "LEAU ix16", // 33
+ "PSHS i8", // 34
+ "PULS i8", // 35
+ "PSHU i8", // 36
+ "PULU i8", // 37
+ "???", // 38
+ "RTS", // 39
+ "ABX", // 3a
+ "RTI", // 3b
+ "CWAI i8", // 3c
+ "MUL", // 3d
+ "???", // 3e
+ "SWI1", // 3f
+ "NEG A", // 40
+ "???", // 41
+ "???", // 42
+ "COM A", // 43
+ "LSR A", // 44
+ "???", // 45
+ "ROR A", // 46
+ "ASR A", // 47
+ "ASL A", // 48
+ "ROL A", // 49
+ "DEC A", // 4a
+ "???", // 4b
+ "INC A", // 4c
+ "TST A", // 4d
+ "???", // 4e
+ "CLR A", // 4f
+ "NEG B", // 50
+ "???", // 51
+ "???", // 52
+ "COM B", // 53
+ "LSR B", // 54
+ "???", // 55
+ "ROR B", // 56
+ "ASR B", // 57
+ "ASL B", // 58
+ "ROL B", // 59
+ "DEC B", // 5a
+ "???", // 5b
+ "INC B", // 5c
+ "TST B", // 5d
+ "???", // 5e
+ "CLR B", // 5f
+ "NEG ix16", // 60
+ "???", // 61
+ "???", // 62
+ "COM ix16", // 63
+ "LSR ix16", // 64
+ "???", // 65
+ "ROR ix16", // 66
+ "ASR ix16", // 67
+ "ASL ix16", // 68
+ "ROL ix16", // 69
+ "DEC ix16", // 6a
+ "???", // 6b
+ "INC ix16", // 6c
+ "TST ix16", // 6d
+ "JMP ix16", // 6e
+ "CLR ix16", // 6f
+ "NEG ex16", // 70
+ "???", // 71
+ "???", // 72
+ "COM ex16", // 73
+ "LSR ex16", // 74
+ "???", // 75
+ "ROR ex16", // 76
+ "ASR ex16", // 77
+ "ASL ex16", // 78
+ "ROL ex16", // 79
+ "DEC ex16", // 7a
+ "???", // 7b
+ "INC ex16", // 7c
+ "TST ex16", // 7d
+ "JMP ex16", // 7e
+ "CLR ex16", // 7f
+ "SUB A,i8", // 80
+ "CMP A,i8", // 81
+ "SBC A,i8", // 82
+ "SUB D,i16", // 83
+ "AND A,i8", // 84
+ "BIT A,i8", // 85
+ "LD A,i8", // 86
+ "???", // 87
+ "EOR A,i8", // 88
+ "ADC A,i8", // 89
+ "OR A,i8", // 8a
+ "ADD A,i8", // 8b
+ "CMP X,i16", // 8c
+ "BSR i8", // 8d
+ "LD X,i16", // 8e
+ "???", // 8f
+ "SUB A,DP+i8", // 90
+ "CMP A,DP+i8", // 91
+ "SBC A,DP+i8", // 92
+ "SUB D,DP+i8", // 93
+ "AND A,DP+i8", // 94
+ "BIT A,DP+i8", // 95
+ "LD A,DP+i8", // 96
+ "ST A,DP+i8", // 97
+ "EOR A,DP+i8", // 98
+ "ADC A,DP+i8", // 99
+ "OR A,DP+i8", // 9a
+ "ADD A,DP+i8", // 9b
+ "CMP X,DP+i8", // 9c
+ "JSR DP+i8", // 9d
+ "LD X,DP+i8", // 9e
+ "ST X,DP+i8", // 9f
+ "SUB A,ix16", // a0
+ "CMP A,ix16", // a1
+ "SBC A,ix16", // a2
+ "SUB D,ix16", // a3
+ "AND A,ix16", // a4
+ "BIT A,ix16", // a5
+ "LD A,ix16", // a6
+ "ST A,ix16", // a7
+ "EOR A,ix16", // a8
+ "ADC A,ix16", // a9
+ "OR A,ix16", // aa
+ "ADD A,ix16", // ab
+ "CMP X,ix16", // ac
+ "JSR ix16", // ad
+ "LD X,ix16", // ae
+ "ST X,ix16", // af
+ "SUB A,ex16", // b0
+ "CMP A,ex16", // b1
+ "SBC A,ex16", // b2
+ "SUB D,ex16", // b3
+ "AND A,ex16", // b4
+ "BIT A,ex16", // b5
+ "LD A,ex16", // b6
+ "ST A,ex16", // b7
+ "EOR A,ex16", // b8
+ "ADC A,ex16", // b9
+ "OR A,ex16", // ba
+ "ADD A,ex16", // bb
+ "CMP X,ex16", // bc
+ "JSR ex16", // bd
+ "LD X,ex16", // be
+ "ST X,ex16", // bf
+ "SUB B,i8", // c0
+ "CMP B,i8", // c1
+ "SBC B,i8", // c2
+ "ADD D,i16", // c3
+ "AND B,i8", // c4
+ "BIT B,i8", // c5
+ "LD B,i8", // c6
+ "???", // c7
+ "EOR B,i8", // c8
+ "ADC B,i8", // c9
+ "OR B,i8", // ca
+ "ADD B,i8", // cb
+ "LD D,i16", // cc
+ "???", // cd
+ "LD U,i16", // ce
+ "???", // cf
+ "SUB B,DP+i8", // d0
+ "CMP B,DP+i8", // d1
+ "SBC B,DP+i8", // d2
+ "ADD D,DP+i8", // d3
+ "AND B,DP+i8", // d4
+ "BIT B,DP+i8", // d5
+ "LD B,DP+i8", // d6
+ "ST B,DP+i8", // d7
+ "EOR B,DP+i8", // d8
+ "ADC B,DP+i8", // d9
+ "OR B,DP+i8", // da
+ "ADD B,DP+i8", // db
+ "LD D,DP+i8", // dc
+ "ST D,DP+i8", // dd
+ "LD U,DP+i8", // de
+ "ST U,DP+i8", // df
+ "SUB B,ix16", // e0
+ "CMP B,ix16", // e1
+ "SBC B,ix16", // e2
+ "ADD D,ix16", // e3
+ "AND B,ix16", // e4
+ "BIT B,ix16", // e5
+ "LD B,ix16", // e6
+ "ST B,ix16", // e7
+ "EOR B,ix16", // e8
+ "ADC B,ix16", // e9
+ "OR B,ix16", // ea
+ "ADD B,ix16", // eb
+ "LD D,ix16", // ec
+ "ST D,ix16", // ed
+ "LD U,ix16", // ee
+ "ST U,ix16", // ef
+ "SUB B,ex16", // f0
+ "CMP B,ex16", // f1
+ "SBC B,ex16", // f2
+ "ADD D,ex16", // f3
+ "AND B,ex16", // f4
+ "BIT B,ex16", // f5
+ "LD B,ex16", // f6
+ "ST B,ex16", // f7
+ "EOR B,ex16", // f8
+ "ADC B,ex16", // f9
+ "OR B,ex16", // fa
+ "ADD B,ex16", // fb
+ "LD D,ex16", // fc
+ "ST D,ex16", // fd
+ "LD U,ex16", // fe
+ "ST U,ex16", // ff
+ };
+
+ public static string Disassemble(ushort addr, Func reader, out ushort size)
+ {
+ ushort origaddr = addr;
+ List bytes = new List();
+ bytes.Add(reader(addr++));
+
+ string result = table[bytes[0]];
+
+ if (result.Contains("i8"))
+ {
+ byte d = reader(addr++);
+ bytes.Add(d);
+ result = result.Replace("i8", string.Format("#{0:X2}h", d));
+ }
+ else if (result.Contains("i16"))
+ {
+ byte dhi = reader(addr++);
+ byte dlo = reader(addr++);
+ bytes.Add(dhi);
+ bytes.Add(dlo);
+ result = result.Replace("i16", string.Format("#{0:X2}{1:X2}h", dhi, dlo));
+ }
+ else if (result.Contains("ex16"))
+ {
+ byte dhi = reader(addr++);
+ byte dlo = reader(addr++);
+ bytes.Add(dhi);
+ bytes.Add(dlo);
+ result = result.Replace("ex16", "(" + string.Format("#{0:X2}{1:X2}h", dhi, dlo) + ")");
+ }
+ else if (result.Contains("ix16"))
+ {
+ byte d = reader(addr++);
+ bytes.Add(d);
+
+ string temp_reg = "";
+
+ switch ((d >> 5) & 3)
+ {
+ case 0: temp_reg = "X"; break;
+ case 1: temp_reg = "Y"; break;
+ case 2: temp_reg = "US"; break;
+ case 3: temp_reg = "SP"; break;
+ }
+
+ if ((d & 0x80) == 0)
+ {
+ short tempdis = (short)(d & 0x1F);
+ if (tempdis >= 16)
+ tempdis -= 32;
+
+ result = result.Replace("ix16", temp_reg + " + ea");
+ result = result.Replace("ea", string.Format("{0:N}h", tempdis));
+ }
+ else
+ {
+ if ((d & 0x10) == 0x10)
+ {
+ switch (d & 0xF)
+ {
+ case 0x0:
+ result = result.Replace("ix16", "???");
+ break;
+ case 0x1:
+ result = result.Replace("ix16","(" + temp_reg + ")++");
+ break;
+ case 0x2:
+ result = result.Replace("ix16", "???");
+ break;
+ case 0x3:
+ result = result.Replace("ix16", "--(" + temp_reg + ")");
+ break;
+ case 0x4:
+ result = result.Replace("ix16", "(" + temp_reg + ")");
+ break;
+ case 0x5:
+ result = result.Replace("ix16", "(" + temp_reg + " + B)");
+ break;
+ case 0x6:
+ result = result.Replace("ix16", "(" + temp_reg + " + A)");
+ break;
+ case 0x7:
+ result = result.Replace("ix16", "???");
+ break;
+ case 0x8:
+ byte e = reader(addr++);
+ bytes.Add(e);
+ result = result.Replace("ix16", "(" + temp_reg + " + ea)");
+ result = result.Replace("ea", string.Format("{0:X2}h", e));
+ break;
+ case 0x9:
+ byte f = reader(addr++);
+ bytes.Add(f);
+ byte g = reader(addr++);
+ bytes.Add(g);
+ result = result.Replace("ix16", "(" + temp_reg + " + ea)");
+ result = result.Replace("ea", string.Format("{0:X2}{1:X2}h", f, g));
+ break;
+ case 0xA:
+ result = result.Replace("ix16", "???");
+ break;
+ case 0xB:
+ result = result.Replace("ix16", "(" + temp_reg + " + D)");
+ break;
+ case 0xC:
+ temp_reg = "PC";
+ byte h = reader(addr++);
+ bytes.Add(h);
+ result = result.Replace("ix16", "(" + temp_reg + " + ea)");
+ result = result.Replace("ea", string.Format("{0:X2}h", h));
+ break;
+ case 0xD:
+ temp_reg = "PC";
+ byte i = reader(addr++);
+ bytes.Add(i);
+ byte j = reader(addr++);
+ bytes.Add(j);
+ result = result.Replace("ix16", "(" + temp_reg + " + ea)");
+ result = result.Replace("ea", string.Format("{0:X2}{1:X2}h", i, j));
+ break;
+ case 0xE:
+ result = result.Replace("ix16", "???");
+ break;
+ case 0xF:
+ if (((d >> 5) & 3) == 0)
+ {
+ byte k = reader(addr++);
+ bytes.Add(k);
+ byte l = reader(addr++);
+ bytes.Add(l);
+ result = result.Replace("ix16", "(" + string.Format("{0:X2}{1:X2}h", k, l) + ")");
+ }
+ else
+ {
+ result = result.Replace("ix16", "???");
+ }
+ break;
+ }
+ }
+ else
+ {
+ switch (d & 0xF)
+ {
+ case 0x0:
+ result = result.Replace("ix16", temp_reg + "+");
+ break;
+ case 0x1:
+ result = result.Replace("ix16", temp_reg + "++");
+ break;
+ case 0x2:
+ result = result.Replace("ix16", "-" + temp_reg);
+ break;
+ case 0x3:
+ result = result.Replace("ix16", "--" + temp_reg);
+ break;
+ case 0x4:
+ result = result.Replace("ix16", temp_reg);
+ break;
+ case 0x5:
+ result = result.Replace("ix16", temp_reg + " + B");
+ break;
+ case 0x6:
+ result = result.Replace("ix16", temp_reg + " + A");
+ break;
+ case 0x7:
+ result = result.Replace("ix16", "???");
+ break;
+ case 0x8:
+ byte e = reader(addr++);
+ bytes.Add(e);
+ result = result.Replace("ix16", temp_reg + " + ea");
+ result = result.Replace("ea", string.Format("{0:X2}h", e));
+ break;
+ case 0x9:
+ byte f = reader(addr++);
+ bytes.Add(f);
+ byte g = reader(addr++);
+ bytes.Add(g);
+ result = result.Replace("ix16", temp_reg + " + ea");
+ result = result.Replace("ea", string.Format("{0:X2}{1:X2}h", f, g));
+ break;
+ case 0xA:
+ result = result.Replace("ix16", "???");
+ break;
+ case 0xB:
+ result = result.Replace("ix16", temp_reg + " + D");
+ break;
+ case 0xC:
+ temp_reg = "PC";
+ byte h = reader(addr++);
+ bytes.Add(h);
+ result = result.Replace("ix16", temp_reg + " + ea");
+ result = result.Replace("ea", string.Format("{0:X2}h", h));
+ break;
+ case 0xD:
+ temp_reg = "PC";
+ byte i = reader(addr++);
+ bytes.Add(i);
+ byte j = reader(addr++);
+ bytes.Add(j);
+ result = result.Replace("ix16", temp_reg + " + ea");
+ result = result.Replace("ea", string.Format("{0:X2}{1:X2}h", i, j));
+ break;
+ case 0xE:
+ result = result.Replace("ix16", "???");
+ break;
+ case 0xF:
+ result = result.Replace("ix16", "???");
+ break;
+ }
+ }
+ }
+ }
+ else if (result.Contains("r8"))
+ {
+ byte d = reader(addr++);
+ bytes.Add(d);
+ int offs = d;
+ if (offs >= 128)
+ offs -= 256;
+ result = result.Replace("r8", string.Format("{0:X4}h", (ushort)(addr + offs)));
+ }
+ StringBuilder ret = new StringBuilder();
+ ret.Append(string.Format("{0:X4}: ", origaddr));
+ foreach (var b in bytes)
+ ret.Append(string.Format("{0:X2} ", b));
+ while (ret.Length < 22)
+ ret.Append(' ');
+ ret.Append(result);
+ size = (ushort)(addr - origaddr);
+ return ret.ToString();
+ }
+ }
+}
diff --git a/BizHawk.Emulation.Cores/CPUs/MC6800/Execute.cs b/BizHawk.Emulation.Cores/CPUs/MC6800/Execute.cs
new file mode 100644
index 0000000000..31a5068102
--- /dev/null
+++ b/BizHawk.Emulation.Cores/CPUs/MC6800/Execute.cs
@@ -0,0 +1,285 @@
+using System;
+
+namespace BizHawk.Emulation.Common.Components.MC6800
+{
+ public partial class MC6800
+ {
+ public ulong TotalExecutedCycles;
+
+ // variables for executing instructions
+ public int instr_pntr = 0;
+ public ushort[] cur_instr = new ushort[60];
+ public int opcode_see;
+
+ public int IRQS;
+ public int irq_pntr;
+
+ ushort reg_d_ad;
+ ushort reg_h_ad;
+ ushort reg_l_ad;
+
+ public void FetchInstruction(byte opcode)
+ {
+ opcode_see = opcode;
+ switch (opcode)
+ {
+ case 0x00: ILLEGAL(); break; // ILLEGAL
+ case 0x01: NOP_(); break; // NOP (Inherent)
+ case 0x02: ILLEGAL(); break; // ILLEGAL
+ case 0x03: ILLEGAL(); break; // ILLEGAL
+ case 0x04: ILLEGAL(); break; // ILLEGAL
+ case 0x05: ILLEGAL(); break; // ILLEGAL
+ case 0x06: REG_OP(TAP, A); break; // TAP (Inherent)
+ case 0x07: REG_OP(TPA, A); break; // TPA (Inherent)
+ case 0x08: REG_OP_16(INX, X); break; // INX (Inherent)
+ case 0x09: REG_OP_16(DEX, X); break; // DEX (Inherent)
+ case 0x0A: REG_OP(CLV, CC); break; // CLV (Inherent)
+ case 0x0B: REG_OP(SEV, CC); break; // SEV (Inherent)
+ case 0x0C: REG_OP(CLC, CC); break; // CLC (Inherent)
+ case 0x0D: REG_OP(SEC, CC); break; // SEC (Inherent)
+ case 0x0E: REG_OP(CLI, CC); break; // CLI (Inherent)
+ case 0x0F: REG_OP(SEI, CC); break; // SEI (Inherent)
+ case 0x10: NOP_(); break; // Page 2
+ case 0x11: NOP_(); break; // Page 3
+ case 0x12: ILLEGAL(); break; // NOP (Inherent)
+ case 0x13: ILLEGAL(); break; // SYNC (Inherent)
+ case 0x14: ILLEGAL(); break; // ILLEGAL
+ case 0x15: ILLEGAL(); break; // ILLEGAL
+ case 0x16: LBR_(true); break; // LBRA (Relative)
+ case 0x17: LBSR_(); break; // LBSR (Relative)
+ case 0x18: ILLEGAL(); break; // ILLEGAL
+ case 0x19: REG_OP(DA, A); break; // DAA (Inherent)
+ case 0x1A: ILLEGAL(); break; // ORCC (Immediate)
+ case 0x1B: ILLEGAL(); break; // ILLEGAL
+ case 0x1C: ILLEGAL(); break; // ANDCC (Immediate)
+ case 0x1D: ILLEGAL(); break; // SEX (Inherent)
+ case 0x1E: ILLEGAL(); break; // EXG (Immediate)
+ case 0x1F: ILLEGAL(); break; // TFR (Immediate)
+ case 0x20: BR_(true); break; // BRA (Relative)
+ case 0x21: BR_(false); break; // BRN (Relative)
+ case 0x22: BR_(!(FlagC | FlagZ)); break; // BHI (Relative)
+ case 0x23: BR_(FlagC | FlagZ); break; // BLS (Relative)
+ case 0x24: BR_(!FlagC); break; // BHS , BCC (Relative)
+ case 0x25: BR_(FlagC); break; // BLO , BCS (Relative)
+ case 0x26: BR_(!FlagZ); break; // BNE (Relative)
+ case 0x27: BR_(FlagZ); break; // BEQ (Relative)
+ case 0x28: BR_(!FlagV); break; // BVC (Relative)
+ case 0x29: BR_(FlagV); break; // BVS (Relative)
+ case 0x2A: BR_(!FlagN); break; // BPL (Relative)
+ case 0x2B: BR_(FlagN); break; // BMI (Relative)
+ case 0x2C: BR_(FlagN == FlagV); break; // BGE (Relative)
+ case 0x2D: BR_(FlagN ^ FlagV); break; // BLT (Relative)
+ case 0x2E: BR_((!FlagZ) & (FlagN == FlagV)); break; // BGT (Relative)
+ case 0x2F: BR_(FlagZ | (FlagN ^ FlagV)); break; // BLE (Relative)
+ case 0x30: INDEX_OP(LEAX); break; // LEAX (Indexed)
+ case 0x31: INDEX_OP(LEAY); break; // LEAY (Indexed)
+ case 0x32: INDEX_OP(LEAS); break; // LEAS (Indexed)
+ case 0x33: INDEX_OP(LEAU); break; // LEAU (Indexed)
+ case 0x34: PSH_(SP); break; // PSHS (Immediate)
+ case 0x35: PUL_(SP); break; // PULS (Immediate)
+ case 0x36: PSH_(A); break; // PSHA (Inherent)
+ case 0x37: PSH_(B); break; // PSHB (Inherent)
+ case 0x38: ILLEGAL(); break; // ILLEGAL
+ case 0x39: RTS(); break; // RTS (Inherent)
+ case 0x3A: ABX_(); break; // ABX (Inherent)
+ case 0x3B: RTI(); break; // RTI (Inherent)
+ case 0x3C: CWAI_(); break; // CWAI (Inherent)
+ case 0x3D: MUL_(); break; // MUL (Inherent)
+ case 0x3E: ILLEGAL(); break; // ILLEGAL
+ case 0x3F: SWI1(); break; // SWI (Inherent)
+ case 0x40: REG_OP(NEG, A); break; // NEGA (Inherent)
+ case 0x41: ILLEGAL(); break; // ILLEGAL
+ case 0x42: ILLEGAL(); break; // ILLEGAL
+ case 0x43: REG_OP(COM, A); break; // COMA (Inherent)
+ case 0x44: REG_OP(LSR, A); break; // LSRA (Inherent)
+ case 0x45: ILLEGAL(); break; // ILLEGAL
+ case 0x46: REG_OP(ROR, A); break; // RORA (Inherent)
+ case 0x47: REG_OP(ASR, A); break; // ASRA (Inherent)
+ case 0x48: REG_OP(ASL, A); break; // ASLA , LSLA (Inherent)
+ case 0x49: REG_OP(ROL, A); break; // ROLA (Inherent)
+ case 0x4A: REG_OP(DEC8, A); break; // DECA (Inherent)
+ case 0x4B: ILLEGAL(); break; // ILLEGAL
+ case 0x4C: REG_OP(INC8, A); break; // INCA (Inherent)
+ case 0x4D: REG_OP(TST, A); break; // TSTA (Inherent)
+ case 0x4E: ILLEGAL(); break; // ILLEGAL
+ case 0x4F: REG_OP(CLR, A); break; // CLRA (Inherent)
+ case 0x50: REG_OP(NEG, B); break; // NEGB (Inherent)
+ case 0x51: ILLEGAL(); break; // ILLEGAL
+ case 0x52: ILLEGAL(); break; // ILLEGAL
+ case 0x53: REG_OP(COM, B); break; // COMB (Inherent)
+ case 0x54: REG_OP(LSR, B); break; // LSRB (Inherent)
+ case 0x55: ILLEGAL(); break; // ILLEGAL
+ case 0x56: REG_OP(ROR, B); break; // RORB (Inherent)
+ case 0x57: REG_OP(ASR, B); break; // ASRB (Inherent)
+ case 0x58: REG_OP(ASL, B); break; // ASLB , LSLB (Inherent)
+ case 0x59: REG_OP(ROL, B); break; // ROLB (Inherent)
+ case 0x5A: REG_OP(DEC8, B); break; // DECB (Inherent)
+ case 0x5B: ILLEGAL(); break; // ILLEGAL
+ case 0x5C: REG_OP(INC8, B); break; // INCB (Inherent)
+ case 0x5D: REG_OP(TST, B); break; // TSTB (Inherent)
+ case 0x5E: ILLEGAL(); break; // ILLEGAL
+ case 0x5F: REG_OP(CLR, B); break; // CLRB (Inherent)
+ case 0x60: INDEX_OP(I_NEG); break; // NEG (Indexed)
+ case 0x61: ILLEGAL(); break; // ILLEGAL
+ case 0x62: ILLEGAL(); break; // ILLEGAL
+ case 0x63: INDEX_OP(I_COM); break; // COM (Indexed)
+ case 0x64: INDEX_OP(I_LSR); break; // LSR (Indexed)
+ case 0x65: ILLEGAL(); break; // ILLEGAL
+ case 0x66: INDEX_OP(I_ROR); break; // ROR (Indexed)
+ case 0x67: INDEX_OP(I_ASR); break; // ASR (Indexed)
+ case 0x68: INDEX_OP(I_ASL); break; // ASL , LSL (Indexed)
+ case 0x69: INDEX_OP(I_ROL); break; // ROL (Indexed)
+ case 0x6A: INDEX_OP(I_DEC); break; // DEC (Indexed)
+ case 0x6B: ILLEGAL(); break; // ILLEGAL
+ case 0x6C: INDEX_OP(I_INC); break; // INC (Indexed)
+ case 0x6D: INDEX_OP(I_TST); break; // TST (Indexed)
+ case 0x6E: INDEX_OP(I_JMP); break; // JMP (Indexed)
+ case 0x6F: INDEX_OP(I_CLR); break; // CLR (Indexed)
+ case 0x70: EXT_MEM(NEG); break; // NEG (Extended)
+ case 0x71: ILLEGAL(); break; // ILLEGAL
+ case 0x72: ILLEGAL(); break; // ILLEGAL
+ case 0x73: EXT_MEM(COM); break; // COM (Extended)
+ case 0x74: EXT_MEM(LSR); break; // LSR (Extended)
+ case 0x75: ILLEGAL(); break; // ILLEGAL
+ case 0x76: EXT_MEM(ROR); break; // ROR (Extended)
+ case 0x77: EXT_MEM(ASR); break; // ASR (Extended)
+ case 0x78: EXT_MEM(ASL); break; // ASL , LSL (Extended)
+ case 0x79: EXT_MEM(ROL); break; // ROL (Extended)
+ case 0x7A: EXT_MEM(DEC8); break; // DEC (Extended)
+ case 0x7B: ILLEGAL(); break; // ILLEGAL
+ case 0x7C: EXT_MEM(INC8); break; // INC (Extended)
+ case 0x7D: EXT_MEM(TST); break; // TST (Extended)
+ case 0x7E: JMP_EXT_(); break; // JMP (Extended)
+ case 0x7F: EXT_MEM(CLR); break; // CLR (Extended)
+ case 0x80: REG_OP_IMD(SUB8, A); break; // SUBA (Immediate)
+ case 0x81: REG_OP_IMD(CMP8, A); break; // CMPA (Immediate)
+ case 0x82: REG_OP_IMD(SBC8, A); break; // SBCA (Immediate)
+ case 0x83: IMD_OP_D(SUB16, D); break; // SUBD (Immediate)
+ case 0x84: REG_OP_IMD(AND8, A); break; // ANDA (Immediate)
+ case 0x85: REG_OP_IMD(BIT, A); break; // BITA (Immediate)
+ case 0x86: REG_OP_IMD(LD_8, A); break; // LDA (Immediate)
+ case 0x87: ILLEGAL(); break; // ILLEGAL
+ case 0x88: REG_OP_IMD(XOR8, A); break; // EORA (Immediate)
+ case 0x89: REG_OP_IMD(ADC8, A); break; // ADCA (Immediate)
+ case 0x8A: REG_OP_IMD(OR8, A); break; // ORA (Immediate)
+ case 0x8B: REG_OP_IMD(ADD8, A); break; // ADDA (Immediate)
+ case 0x8C: IMD_CMP_16(CMP16, X); break; // CMPX (Immediate)
+ case 0x8D: BSR_(); break; // BSR (Relative)
+ case 0x8E: REG_OP_LD_16(X); break; // LDX (Immediate)
+ case 0x8F: ILLEGAL(); break; // ILLEGAL
+ case 0x90: DIRECT_MEM_4(SUB8, A); break; // SUBA (Direct)
+ case 0x91: DIRECT_MEM_4(CMP8, A); break; // CMPA (Direct)
+ case 0x92: DIRECT_MEM_4(SBC8, A); break; // SBCA (Direct)
+ case 0x93: DIR_OP_D(SUB16, D); break; // SUBD (Direct)
+ case 0x94: DIRECT_MEM_4(AND8, A); break; // ANDA (Direct)
+ case 0x95: DIRECT_MEM_4(BIT, A); break; // BITA (Direct)
+ case 0x96: DIRECT_MEM_4(LD_8, A); break; // LDA (Direct)
+ case 0x97: DIRECT_ST_4(A); break; // STA (Direct)
+ case 0x98: DIRECT_MEM_4(XOR8, A); break; // EORA (Direct)
+ case 0x99: DIRECT_MEM_4(ADC8, A); break; // ADCA (Direct)
+ case 0x9A: DIRECT_MEM_4(OR8, A); break; // ORA (Direct)
+ case 0x9B: DIRECT_MEM_4(ADD8, A); break; // ADDA (Direct)
+ case 0x9C: DIR_CMP_16(CMP16, X); break; // CMPX (Direct)
+ case 0x9D: REG_OP(ADC8, A); break; // JSR (Direct)
+ case 0x9E: DIR_OP_LD_16(X); break; // LDX (Direct)
+ case 0x9F: DIR_OP_ST_16(X); break; // STX (Direct)
+ case 0xA0: INDEX_OP_REG(I_SUB, A); break; // SUBA (Indexed)
+ case 0xA1: INDEX_OP_REG(I_CMP, A); break; // CMPA (Indexed)
+ case 0xA2: INDEX_OP_REG(I_SBC, A); break; // SBCA (Indexed)
+ case 0xA3: INDEX_OP_REG(I_SUBD, D); break; // SUBD (Indexed)
+ case 0xA4: INDEX_OP_REG(I_AND, A); break; // ANDA (Indexed)
+ case 0xA5: INDEX_OP_REG(I_BIT, A); break; // BITA (Indexed)
+ case 0xA6: INDEX_OP_REG(I_LD, A); break; // LDA (Indexed)
+ case 0xA7: INDEX_OP_REG(I_ST, A); break; // STA (Indexed)
+ case 0xA8: INDEX_OP_REG(I_XOR, A); break; // EORA (Indexed)
+ case 0xA9: INDEX_OP_REG(I_ADC, A); break; // ADCA (Indexed)
+ case 0xAA: INDEX_OP_REG(I_OR, A); break; // ORA (Indexed)
+ case 0xAB: INDEX_OP_REG(I_ADD, A); break; // ADDA (Indexed)
+ case 0xAC: INDEX_OP_REG(I_CMP16, X); break; // CMPX (Indexed)
+ case 0xAD: INDEX_OP(I_JSR); break; // JSR (Indexed)
+ case 0xAE: INDEX_OP_REG(I_LD16, X); break; // LDX (Indexed)
+ case 0xAF: INDEX_OP_REG(I_ST16, X); break; // STX (Indexed)
+ case 0xB0: EXT_REG(SUB8, A); break; // SUBA (Extended)
+ case 0xB1: EXT_REG(CMP8, A); break; // CMPA (Extended)
+ case 0xB2: EXT_REG(SBC8, A); break; // SBCA (Extended)
+ case 0xB3: EXT_OP_D(SUB16, D); break; // SUBD (Extended)
+ case 0xB4: EXT_REG(AND8, A); break; // ANDA (Extended)
+ case 0xB5: EXT_REG(BIT, A); break; // BITA (Extended)
+ case 0xB6: EXT_REG(LD_8, A); break; // LDA (Extended)
+ case 0xB7: EXT_ST(A); break; // STA (Extended)
+ case 0xB8: EXT_REG(XOR8, A); break; // EORA (Extended)
+ case 0xB9: EXT_REG(ADC8, A); break; // ADCA (Extended)
+ case 0xBA: EXT_REG(OR8, A); break; // ORA (Extended)
+ case 0xBB: EXT_REG(ADD8, A); break; // ADDA (Extended)
+ case 0xBC: EXT_CMP_16(CMP16, X); break; // CMPX (Extended)
+ case 0xBD: JSR_EXT(); break; // JSR (Extended)
+ case 0xBE: EXT_OP_LD_16(X); break; // LDX (Extended)
+ case 0xBF: EXT_OP_ST_16(X); break; // STX (Extended)
+ case 0xC0: REG_OP_IMD(SUB8, B); break; // SUBB (Immediate)
+ case 0xC1: REG_OP_IMD(CMP8, B); break; // CMPB (Immediate)
+ case 0xC2: REG_OP_IMD(SBC8, B); break; // SBCB (Immediate)
+ case 0xC3: IMD_OP_D(ADD16, D); break; // ADDD (Immediate)
+ case 0xC4: REG_OP_IMD(AND8, B); break; // ANDB (Immediate)
+ case 0xC5: REG_OP_IMD(BIT, B); break; // BITB (Immediate)
+ case 0xC6: REG_OP_IMD(LD_8, B); break; // LDB (Immediate)
+ case 0xC7: ILLEGAL(); break; // ILLEGAL
+ case 0xC8: REG_OP_IMD(XOR8, B); break; // EORB (Immediate)
+ case 0xC9: REG_OP_IMD(ADC8, B); break; // ADCB (Immediate)
+ case 0xCA: REG_OP_IMD(OR8, B); break; // ORB (Immediate)
+ case 0xCB: REG_OP_IMD(ADD8, B); break; // ADDB (Immediate)
+ case 0xCC: REG_OP_LD_16D(); break; // LDD (Immediate)
+ case 0xCD: ILLEGAL(); break; // ILLEGAL
+ case 0xCE: REG_OP_LD_16(X); break; // LDX (Immediate)
+ case 0xCF: ILLEGAL(); break; // ILLEGAL
+ case 0xD0: DIRECT_MEM_4(SUB8, B); break; // SUBB (Direct)
+ case 0xD1: DIRECT_MEM_4(CMP8, B); break; // CMPB (Direct)
+ case 0xD2: DIRECT_MEM_4(SBC8, B); break; // SBCB (Direct)
+ case 0xD3: DIR_OP_D(ADD16, D); break; // ADDD (Direct)
+ case 0xD4: DIRECT_MEM_4(AND8, B); break; // ANDB (Direct)
+ case 0xD5: DIRECT_MEM_4(BIT, B); break; // BITB (Direct)
+ case 0xD6: DIRECT_MEM_4(LD_8, B); break; // LDB (Direct)
+ case 0xD7: DIRECT_ST_4(B); break; // STB (Direct)
+ case 0xD8: DIRECT_MEM_4(XOR8, B); break; // EORB (Direct)
+ case 0xD9: DIRECT_MEM_4(ADC8, B); break; // ADCB (Direct)
+ case 0xDA: DIRECT_MEM_4(OR8, B); break; // ORB (Direct)
+ case 0xDB: DIRECT_MEM_4(ADD8, B); break; // ADDB (Direct)
+ case 0xDC: DIR_OP_LD_16D(); break; // LDD (Direct)
+ case 0xDD: DIR_OP_ST_16D(); break; // STD (Direct)
+ case 0xDE: DIR_OP_LD_16(X); break; // LDX (Direct)
+ case 0xDF: DIR_OP_ST_16(X); break; // STX (Direct)
+ case 0xE0: INDEX_OP_REG(I_SUB, B); break; // SUBB (Indexed)
+ case 0xE1: INDEX_OP_REG(I_CMP, B); break; // CMPB (Indexed)
+ case 0xE2: INDEX_OP_REG(I_SBC, B); break; // SBCB (Indexed)
+ case 0xE3: INDEX_OP_REG(I_ADDD, D); break; // ADDD (Indexed)
+ case 0xE4: INDEX_OP_REG(I_AND, B); break; // ANDB (Indexed)
+ case 0xE5: INDEX_OP_REG(I_BIT, B); break; // BITB (Indexed)
+ case 0xE6: INDEX_OP_REG(I_LD, B); break; // LDB (Indexed)
+ case 0xE7: INDEX_OP_REG(I_ST, B); break; // STB (Indexed)
+ case 0xE8: INDEX_OP_REG(I_XOR, B); break; // EORB (Indexed)
+ case 0xE9: INDEX_OP_REG(I_ADC, B); break; // ADCB (Indexed)
+ case 0xEA: INDEX_OP_REG(I_OR, B); break; // ORB (Indexed)
+ case 0xEB: INDEX_OP_REG(I_ADD, B); break; // ADDB (Indexed)
+ case 0xEC: INDEX_OP_REG(I_LD16D, D); break; // LDD (Indexed)
+ case 0xED: INDEX_OP_REG(I_ST16D, D); break; // STD (Indexed)
+ case 0xEE: INDEX_OP_REG(I_LD16, X); break; // LDX (Indexed)
+ case 0xEF: INDEX_OP_REG(I_ST16, X); break; // STX (Indexed)
+ case 0xF0: EXT_REG(SUB8, B); break; // SUBB (Extended)
+ case 0xF1: EXT_REG(CMP8, B); break; // CMPB (Extended)
+ case 0xF2: EXT_REG(SBC8, B); break; // SBCB (Extended)
+ case 0xF3: EXT_OP_D(ADD16, D); break; // ADDD (Extended)
+ case 0xF4: EXT_REG(AND8, B); break; // ANDB (Extended)
+ case 0xF5: EXT_REG(BIT, B); break; // BITB (Extended)
+ case 0xF6: EXT_REG(LD_8, B); break; // LDB (Extended)
+ case 0xF7: EXT_ST(B); break; // STB (Extended)
+ case 0xF8: EXT_REG(XOR8, B); break; // EORB (Extended)
+ case 0xF9: EXT_REG(ADC8, B); break; // ADCB (Extended)
+ case 0xFA: EXT_REG(OR8, B); break; // ORB (Extended)
+ case 0xFB: EXT_REG(ADD8, B); break; // ADDB (Extended)
+ case 0xFC: EXT_OP_LD_16D(); break; // LDD (Extended)
+ case 0xFD: EXT_OP_ST_16D(); break; // STD (Extended)
+ case 0xFE: EXT_OP_LD_16(X); break; // LDX (Extended)
+ case 0xFF: EXT_OP_ST_16(X); break; // STX (Extended)
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/BizHawk.Emulation.Cores/CPUs/MC6800/Indexed_Modes.cs b/BizHawk.Emulation.Cores/CPUs/MC6800/Indexed_Modes.cs
new file mode 100644
index 0000000000..b356506e5c
--- /dev/null
+++ b/BizHawk.Emulation.Cores/CPUs/MC6800/Indexed_Modes.cs
@@ -0,0 +1,450 @@
+using System;
+
+namespace BizHawk.Emulation.Common.Components.MC6800
+{
+ public partial class MC6800
+ {
+ public const ushort LEAX = 0;
+ public const ushort LEAY = 1;
+ public const ushort LEAS = 2;
+ public const ushort LEAU = 3;
+ public const ushort I_NEG = 4;
+ public const ushort I_COM = 5;
+ public const ushort I_LSR = 6;
+ public const ushort I_ROR = 7;
+ public const ushort I_ASR = 8;
+ public const ushort I_ASL = 9;
+ public const ushort I_ROL = 10;
+ public const ushort I_DEC = 11;
+ public const ushort I_INC = 12;
+ public const ushort I_TST = 13;
+ public const ushort I_JMP = 14;
+ public const ushort I_CLR = 15;
+ public const ushort I_SUB = 16;
+ public const ushort I_CMP = 17;
+ public const ushort I_SBC = 18;
+ public const ushort I_AND = 19;
+ public const ushort I_BIT = 20;
+ public const ushort I_LD = 21;
+ public const ushort I_ST = 22;
+ public const ushort I_XOR = 23;
+ public const ushort I_ADC = 24;
+ public const ushort I_OR = 25;
+ public const ushort I_ADD = 26;
+ public const ushort I_SUBD = 27;
+ public const ushort I_ADDD = 28;
+ public const ushort I_CMP16 = 29;
+ public const ushort I_JSR = 30;
+ public const ushort I_LD16 = 31;
+ public const ushort I_ST16 = 32;
+ public const ushort I_LD16D = 33;
+ public const ushort I_ST16D = 34;
+ public const ushort I_CMP16D = 35;
+
+ public ushort indexed_op;
+ public ushort indexed_reg;
+ public ushort indexed_op_reg;
+
+ public ushort temp;
+
+ private void INDEX_OP(ushort oper)
+ {
+ indexed_op = oper;
+
+ PopulateCURINSTR(RD_INC_OP, ALU, PC, IDX_DCDE);
+
+ IRQS = -1;
+ }
+
+ private void INDEX_OP_REG(ushort oper, ushort src)
+ {
+ indexed_op = oper;
+ indexed_op_reg = src;
+
+ PopulateCURINSTR(RD_INC_OP, ALU, PC, IDX_DCDE);
+
+ IRQS = -1;
+ }
+
+ private void INDEX_OP_JMP()
+ {
+ PopulateCURINSTR(TR, PC, IDX_EA);
+
+ IRQS = 1;
+ }
+
+ private void INDEX_OP_JSR()
+ {
+ PopulateCURINSTR(TR, ADDR, PC,
+ DEC16, SP,
+ TR, PC, IDX_EA,
+ WR_DEC_LO, SP, ADDR,
+ WR_HI, SP, ADDR);
+
+ IRQS = 5;
+ }
+
+ private void INDEX_OP_LEA(ushort dest)
+ {
+ PopulateCURINSTR(LEA, dest, IDX_EA,
+ IDLE);
+
+ IRQS = 2;
+ }
+
+ private void INDEX_OP_LD()
+ {
+ PopulateCURINSTR(IDLE,
+ RD_INC, ALU, IDX_EA,
+ RD_INC_OP, ALU2, IDX_EA, LD_16, indexed_op_reg, ALU, ALU2);
+
+ IRQS = 3;
+ }
+
+ private void INDEX_OP_ST()
+ {
+ PopulateCURINSTR(IDLE,
+ WR_HI_INC, IDX_EA, indexed_op_reg,
+ WR_DEC_LO, IDX_EA, indexed_op_reg);
+
+ IRQS = 3;
+ }
+
+ private void INDEX_OP_LDD()
+ {
+ PopulateCURINSTR(IDLE,
+ RD_INC, A, IDX_EA,
+ RD_INC_OP, B, IDX_EA, LD_16, ADDR, A, B);
+
+ IRQS = 3;
+ }
+
+ private void INDEX_OP_STD()
+ {
+ PopulateCURINSTR(SET_ADDR, ADDR, A, A,
+ WR_HI_INC, IDX_EA, ADDR,
+ WR_DEC_LO, IDX_EA, B);
+
+ IRQS = 3;
+ }
+
+ private void INDEX_OP_EX4(ushort oper)
+ {
+ PopulateCURINSTR(IDLE,
+ RD_INC_OP, ALU, IDX_EA, oper, indexed_op_reg, ALU);
+
+ IRQS = 2;
+ }
+
+ private void INDEX_OP_EX4_ST()
+ {
+ PopulateCURINSTR(IDLE,
+ WR, IDX_EA, indexed_op_reg);
+
+ IRQS = 2;
+ }
+
+ private void INDEX_OP_EX6(ushort oper)
+ {
+ PopulateCURINSTR(IDLE,
+ RD, ALU, IDX_EA,
+ oper, ALU,
+ WR, IDX_EA, ALU);
+
+ IRQS = 4;
+ }
+
+ private void INDEX_OP_EX6D(ushort oper)
+ {
+ PopulateCURINSTR(IDLE,
+ RD_INC, ALU, IDX_EA,
+ RD_INC_OP, ALU2, IDX_EA, SET_ADDR, ADDR, ALU, ALU2,
+ oper, ADDR);
+
+ IRQS = 4;
+ }
+
+ private void INDEX_CMP_EX6(ushort oper)
+ {
+ PopulateCURINSTR(IDLE,
+ RD_INC, ALU, IDX_EA,
+ RD_INC_OP, ALU2, IDX_EA, SET_ADDR, ADDR, ALU, ALU2,
+ oper, indexed_op_reg, ADDR);
+
+ IRQS = 4;
+ }
+
+ // ALU holds the post byte
+ public void Index_decode()
+ {
+ switch ((Regs[ALU] >> 5) & 3)
+ {
+ case 0: indexed_reg = X; break;
+ case 1: indexed_reg = SP; break;
+ }
+
+ if ((Regs[ALU] & 0x80) == 0)
+ {
+ temp = (ushort)(Regs[ALU] & 0x1F);
+ if ((Regs[ALU] & 0x10) == 0x10)
+ {
+ temp |= 0xFFE0;
+ }
+
+ Regs[IDX_EA] = (ushort)(Regs[indexed_reg] + temp);
+
+ PopulateCURINSTR(IDX_OP_BLD);
+ }
+ else
+ {
+ if ((Regs[ALU] & 0x10) == 0x10)
+ {
+ switch (Regs[ALU] & 0xF)
+ {
+ case 0x0:
+ // Illegal
+ break;
+ case 0x1:
+ Regs[ADDR] = Regs[indexed_reg];
+ PopulateCURINSTR(INC16, indexed_reg,
+ INC16, indexed_reg,
+ RD_INC, ALU, ADDR,
+ RD_INC, ALU2, ADDR,
+ SET_ADDR, IDX_EA, ALU, ALU2,
+ IDX_OP_BLD);
+ break;
+ case 0x2:
+ // Illegal
+ break;
+ case 0x3:
+ Regs[ADDR] = (ushort)(Regs[indexed_reg] - 2);
+ PopulateCURINSTR(DEC16, indexed_reg,
+ DEC16, indexed_reg,
+ RD_INC, ALU, ADDR,
+ RD_INC, ALU2, ADDR,
+ SET_ADDR, IDX_EA, ALU, ALU2,
+ IDX_OP_BLD);
+ break;
+ case 0x4:
+ Regs[ADDR] = Regs[indexed_reg];
+ PopulateCURINSTR(RD_INC, ALU, ADDR,
+ RD_INC_OP, ALU2, ADDR, SET_ADDR, IDX_EA, ALU, ALU2,
+ IDX_OP_BLD);
+ break;
+ case 0x5:
+ Regs[ADDR] = (ushort)(Regs[indexed_reg] + (((Regs[B] & 0x80) == 0x80) ? (Regs[B] | 0xFF00) : Regs[B]));
+ PopulateCURINSTR(RD_INC, ALU, ADDR,
+ RD_INC, ALU2, ADDR,
+ SET_ADDR, IDX_EA, ALU, ALU2,
+ IDX_OP_BLD);
+ break;
+ case 0x6:
+ Regs[ADDR] = (ushort)(Regs[indexed_reg] + (((Regs[A] & 0x80) == 0x80) ? (Regs[A] | 0xFF00) : Regs[A]));
+ PopulateCURINSTR(RD_INC, ALU, ADDR,
+ RD_INC, ALU2, ADDR,
+ SET_ADDR, IDX_EA, ALU, ALU2,
+ IDX_OP_BLD);
+ break;
+ case 0x7:
+ // Illegal
+ break;
+ case 0x8:
+ Regs[ADDR] = Regs[indexed_reg];
+ PopulateCURINSTR(RD_INC_OP, ALU2, PC, ADD8BR, ADDR, ALU2,
+ RD_INC, ALU, ADDR,
+ RD_INC_OP, ALU2, ADDR, SET_ADDR, IDX_EA, ALU, ALU2,
+ IDX_OP_BLD);
+ break;
+ case 0x9:
+ Regs[ADDR] = Regs[indexed_reg];
+ PopulateCURINSTR(RD_INC, ALU, PC,
+ RD_INC, ALU2, PC,
+ SET_ADDR, IDX_EA, ALU, ALU2,
+ ADD16BR, ADDR, IDX_EA,
+ RD_INC, ALU, ADDR,
+ RD_INC_OP, ALU2, ADDR, SET_ADDR, IDX_EA, ALU, ALU2,
+ IDX_OP_BLD);
+ break;
+ case 0xA:
+ // Illegal
+ break;
+ case 0xB:
+ Regs[ADDR] = Regs[indexed_reg];
+ PopulateCURINSTR(IDLE,
+ IDLE,
+ SET_ADDR, IDX_EA, A, B,
+ ADD16BR, ADDR, IDX_EA,
+ RD_INC, ALU, ADDR,
+ RD_INC_OP, ALU2, ADDR, SET_ADDR, IDX_EA, ALU, ALU2,
+ IDX_OP_BLD);
+ break;
+ case 0xC:
+ indexed_reg = PC;
+ Regs[ADDR] = Regs[indexed_reg];
+ PopulateCURINSTR(RD_INC_OP, ALU2, PC, ADD8BR, ADDR, ALU2,
+ RD_INC, ALU, ADDR,
+ RD_INC_OP, ALU2, ADDR, SET_ADDR, IDX_EA, ALU, ALU2,
+ IDX_OP_BLD);
+ break;
+ case 0xD:
+ indexed_reg = PC;
+ Regs[ADDR] = Regs[indexed_reg];
+ PopulateCURINSTR(IDLE,
+ RD_INC, ALU, PC,
+ RD_INC, ALU2, PC,
+ SET_ADDR, IDX_EA, ALU, ALU2,
+ ADD16BR, ADDR, IDX_EA,
+ RD_INC, ALU, ADDR,
+ RD_INC_OP, ALU2, ADDR, SET_ADDR, IDX_EA, ALU, ALU2,
+ IDX_OP_BLD);
+ break;
+ case 0xE:
+ // Illegal
+ break;
+ case 0xF:
+ if (((Regs[ALU] >> 5) & 3) == 0)
+ {
+ PopulateCURINSTR(RD_INC, ALU, PC,
+ RD_INC_OP, ALU2, PC, SET_ADDR, ADDR, ALU, ALU2,
+ RD_INC, ALU, ADDR,
+ RD_INC_OP, ALU2, ADDR, SET_ADDR, IDX_EA, ALU, ALU2,
+ IDX_OP_BLD);
+ }
+ else
+ {
+ // illegal
+ }
+ break;
+ }
+ }
+ else
+ {
+ switch (Regs[ALU] & 0xF)
+ {
+ case 0x0:
+ Regs[IDX_EA] = Regs[indexed_reg];
+ PopulateCURINSTR(INC16, indexed_reg,
+ IDX_OP_BLD);
+ break;
+ case 0x1:
+ Regs[IDX_EA] = Regs[indexed_reg];
+ PopulateCURINSTR(INC16, indexed_reg,
+ INC16, indexed_reg,
+ IDX_OP_BLD);
+ break;
+ case 0x2:
+ Regs[IDX_EA] = (ushort)(Regs[indexed_reg] - 1);
+ PopulateCURINSTR(DEC16, indexed_reg,
+ IDX_OP_BLD);
+ break;
+ case 0x3:
+ Regs[IDX_EA] = (ushort)(Regs[indexed_reg] - 2);
+ PopulateCURINSTR(DEC16, indexed_reg,
+ DEC16, indexed_reg,
+ IDX_OP_BLD);
+ break;
+ case 0x4:
+ Regs[IDX_EA] = Regs[indexed_reg];
+ Index_Op_Builder();
+ return; // need to return here or else we run into the code below invalidating irq_pntr
+ break;
+ case 0x5:
+ Regs[IDX_EA] = (ushort)(Regs[indexed_reg] + (((Regs[B] & 0x80) == 0x80) ? (Regs[B] | 0xFF00) : Regs[B]));
+ PopulateCURINSTR(IDX_OP_BLD);
+ break;
+ case 0x6:
+ Regs[IDX_EA] = (ushort)(Regs[indexed_reg] + (((Regs[A] & 0x80) == 0x80) ? (Regs[A] | 0xFF00) : Regs[A]));
+ PopulateCURINSTR(IDX_OP_BLD);
+ break;
+ case 0x7:
+ // Illegal
+ break;
+ case 0x8:
+ PopulateCURINSTR(RD_INC_OP, ALU2, PC, EA_8);
+ break;
+ case 0x9:
+ PopulateCURINSTR(RD_INC, ALU, PC,
+ RD_INC, ALU2, PC,
+ SET_ADDR, ADDR, ALU, ALU2,
+ EA_16);
+ break;
+ case 0xA:
+ // Illegal
+ break;
+ case 0xB:
+ PopulateCURINSTR(IDLE,
+ IDLE,
+ SET_ADDR, ADDR, A, B,
+ EA_16);
+ break;
+ case 0xC:
+ indexed_reg = PC;
+ PopulateCURINSTR(RD_INC_OP, ALU2, PC, EA_8);
+ break;
+ case 0xD:
+ indexed_reg = PC;
+ PopulateCURINSTR(IDLE,
+ RD_INC, ALU, PC,
+ RD_INC, ALU2, PC,
+ SET_ADDR, ADDR, ALU, ALU2,
+ EA_16);
+ break;
+ case 0xE:
+ // Illegal
+ break;
+ case 0xF:
+ // Illegal
+ break;
+ }
+ }
+ }
+
+ instr_pntr = 0;
+ irq_pntr = 100;
+ }
+
+ public void Index_Op_Builder()
+ {
+ switch(indexed_op)
+ {
+ case LEAX: INDEX_OP_LEA(X); break; // LEAX
+ case LEAS: INDEX_OP_LEA(SP); break; // LEAS
+ case I_NEG: INDEX_OP_EX6(NEG); break; // NEG
+ case I_COM: INDEX_OP_EX6(COM); break; // COM
+ case I_LSR: INDEX_OP_EX6(LSR); break; // LSR
+ case I_ROR: INDEX_OP_EX6(ROR); break; // ROR
+ case I_ASR: INDEX_OP_EX6(ASR); break; // ASR
+ case I_ASL: INDEX_OP_EX6(ASL); break; // ASL
+ case I_ROL: INDEX_OP_EX6(ROL); break; // ROL
+ case I_DEC: INDEX_OP_EX6(DEC8); break; // DEC
+ case I_INC: INDEX_OP_EX6(INC8); break; // INC
+ case I_TST: INDEX_OP_EX6(TST); break; // TST
+ case I_JMP: INDEX_OP_JMP(); break; // JMP
+ case I_CLR: INDEX_OP_EX6(CLR); break; // CLR
+ case I_SUB: INDEX_OP_EX4(SUB8); break; // SUB A,B
+ case I_CMP: INDEX_OP_EX4(CMP8); break; // CMP A,B
+ case I_SBC: INDEX_OP_EX4(SBC8); break; // SBC A,B
+ case I_AND: INDEX_OP_EX4(AND8); break; // AND A,B
+ case I_BIT: INDEX_OP_EX4(BIT); break; // BIT A,B
+ case I_LD: INDEX_OP_EX4(LD_8); break; // LD A,B
+ case I_ST: INDEX_OP_EX4_ST(); break; // ST A,B
+ case I_XOR: INDEX_OP_EX4(XOR8); break; // XOR A,B
+ case I_ADC: INDEX_OP_EX4(ADC8); break; // ADC A,B
+ case I_OR: INDEX_OP_EX4(OR8); break; // OR A,B
+ case I_ADD: INDEX_OP_EX4(ADD8); break; // ADD A,B
+ case I_SUBD: INDEX_OP_EX6D(SUB16); break; // SUB D
+ case I_ADDD: INDEX_OP_EX6D(ADD16); break; // ADD D
+ case I_CMP16: INDEX_CMP_EX6(CMP16); break; // CMP X, Y, SP, US
+ case I_JSR: INDEX_OP_JSR(); break; // JSR
+ case I_LD16: INDEX_OP_LD(); break; // LD X, Y, SP, US
+ case I_ST16: INDEX_OP_ST(); break; // ST X, Y, SP, US
+ case I_LD16D: INDEX_OP_LDD(); break; // LD D
+ case I_ST16D: INDEX_OP_STD(); break; // ST D
+ case I_CMP16D: INDEX_OP_EX6D(CMP16D); break; // CMP D
+ }
+
+ instr_pntr = 0;
+ irq_pntr = -1;
+ }
+ }
+}
diff --git a/BizHawk.Emulation.Cores/CPUs/MC6800/Interrupts.cs b/BizHawk.Emulation.Cores/CPUs/MC6800/Interrupts.cs
new file mode 100644
index 0000000000..ee76dfff88
--- /dev/null
+++ b/BizHawk.Emulation.Cores/CPUs/MC6800/Interrupts.cs
@@ -0,0 +1,82 @@
+using System;
+
+namespace BizHawk.Emulation.Common.Components.MC6800
+{
+ public partial class MC6800
+ {
+ private void IRQ_()
+ {
+ Regs[ADDR] = 0xFFF8;
+ PopulateCURINSTR(IDLE,
+ SET_E,
+ DEC16, SP,
+ WR_DEC_LO, SP, PC,
+ WR_DEC_HI, SP, PC,
+ WR_DEC_LO, SP, X,
+ WR_DEC_HI, SP, X,
+ WR_DEC_LO, SP, DP,
+ WR_DEC_LO, SP, B,
+ WR_DEC_LO, SP, A,
+ WR, SP, CC,
+ SET_I,
+ RD_INC, ALU, ADDR,
+ RD_INC, ALU2, ADDR,
+ SET_ADDR, PC, ALU, ALU2);
+
+ IRQS = 19;
+ }
+
+ private void FIRQ_()
+ {
+ Regs[ADDR] = 0xFFF6;
+ PopulateCURINSTR(IDLE,
+ CLR_E,
+ DEC16, SP,
+ WR_DEC_LO, SP, PC,
+ WR_DEC_HI, SP, PC,
+ WR, SP, CC,
+ SET_F_I,
+ RD_INC, ALU, ADDR,
+ RD_INC, ALU2, ADDR,
+ SET_ADDR, PC, ALU, ALU2);
+
+ IRQS = 10;
+ }
+
+ private void NMI_()
+ {
+ Regs[ADDR] = 0xFFFC;
+ PopulateCURINSTR(IDLE,
+ SET_E,
+ DEC16, SP,
+ WR_DEC_LO, SP, PC,
+ WR_DEC_HI, SP, PC,
+ WR_DEC_LO, SP, X,
+ WR_DEC_HI, SP, X,
+ WR_DEC_LO, SP, DP,
+ WR_DEC_LO, SP, B,
+ WR_DEC_LO, SP, A,
+ WR, SP, CC,
+ SET_F_I,
+ RD_INC, ALU, ADDR,
+ RD_INC, ALU2, ADDR,
+ SET_ADDR, PC, ALU, ALU2);
+
+ IRQS = 19;
+ }
+
+ public bool NMIPending;
+ public bool FIRQPending;
+ public bool IRQPending;
+ public bool IN_SYNC;
+
+ public Action IRQCallback = delegate () { };
+ public Action FIRQCallback = delegate () { };
+ public Action NMICallback = delegate () { };
+
+ private void ResetInterrupts()
+ {
+ IN_SYNC = false;
+ }
+ }
+}
\ No newline at end of file
diff --git a/BizHawk.Emulation.Cores/CPUs/MC6800/MC6800.cs b/BizHawk.Emulation.Cores/CPUs/MC6800/MC6800.cs
new file mode 100644
index 0000000000..f13070fc08
--- /dev/null
+++ b/BizHawk.Emulation.Cores/CPUs/MC6800/MC6800.cs
@@ -0,0 +1,695 @@
+using System;
+
+using BizHawk.Common;
+
+// Motorola Corp 6800
+namespace BizHawk.Emulation.Common.Components.MC6800
+{
+ public sealed partial class MC6800
+ {
+ // operations that can take place in an instruction
+ public const ushort IDLE = 0;
+ public const ushort OP = 1;
+ public const ushort RD = 2;
+ public const ushort WR = 3;
+ public const ushort TR = 4;
+ public const ushort ADD16BR = 5;
+ public const ushort ADD8 = 6;
+ public const ushort SUB8 = 7;
+ public const ushort ADC8 = 8;
+ public const ushort SBC8 = 9;
+ public const ushort INC16 = 10;
+ public const ushort INC8 = 11;
+ public const ushort DEC16 = 12;
+ public const ushort DEC8 = 13;
+ public const ushort ROL = 14;
+ public const ushort ROR = 15;
+ public const ushort COM = 16;
+ public const ushort DA = 17;
+ public const ushort AND8 = 18;
+ public const ushort XOR8 = 19;
+ public const ushort OR8 = 20;
+ public const ushort ASL = 21;
+ public const ushort ASR = 22;
+ public const ushort LSR = 23;
+ public const ushort BIT = 24;
+ public const ushort CWAI = 25;
+ public const ushort SYNC = 26;
+ public const ushort RD_INC = 27;
+ public const ushort RD_INC_OP = 28;
+ public const ushort WR_DEC_LO = 29;
+ public const ushort WR_DEC_HI = 30;
+ public const ushort WR_HI = 31;
+ public const ushort SET_ADDR = 32;
+ public const ushort NEG = 33;
+ public const ushort TST = 34;
+ public const ushort CLR = 35;
+ public const ushort SEX = 38;
+ public const ushort EXG = 39;
+ public const ushort TFR = 40;
+ public const ushort ADD8BR = 41;
+ public const ushort ABX = 42;
+ public const ushort MUL = 43;
+ public const ushort JPE = 44;
+ public const ushort IDX_DCDE = 45;
+ public const ushort IDX_OP_BLD = 46;
+ public const ushort EA_8 = 47;
+ public const ushort EA_16 = 48;
+ public const ushort WR_DEC_LO_OP = 51;
+ public const ushort WR_DEC_HI_OP = 52;
+ public const ushort WR_HI_INC = 53;
+ public const ushort SET_F_I = 55;
+ public const ushort SET_I = 56;
+ public const ushort SET_E = 57;
+ public const ushort ANDCC = 58;
+ public const ushort CMP8 = 59;
+ public const ushort SUB16 = 60;
+ public const ushort ADD16 = 61;
+ public const ushort CMP16 = 62;
+ public const ushort CMP16D = 63;
+ public const ushort LD_8 = 64;
+ public const ushort LD_16 = 65;
+ public const ushort LEA = 66;
+ public const ushort CLR_E = 67;
+ public const ushort TAP = 68;
+ public const ushort TPA = 69;
+ public const ushort INX = 70;
+ public const ushort DEX = 71;
+ public const ushort CLV = 72;
+ public const ushort SEV = 73;
+ public const ushort CLC = 74;
+ public const ushort SEC = 75;
+ public const ushort CLI = 76;
+ public const ushort SEI = 77;
+
+ public MC6800()
+ {
+ Reset();
+ }
+
+ public void Reset()
+ {
+ ResetRegisters();
+ ResetInterrupts();
+ TotalExecutedCycles = 0;
+ Regs[PC] = 0xFFFE;
+ PopulateCURINSTR(IDLE,
+ IDLE,
+ IDLE,
+ RD_INC, ALU, PC,
+ RD_INC, ALU2, PC,
+ SET_ADDR, PC, ALU, ALU2);
+
+ IRQS = 6;
+ instr_pntr = irq_pntr = 0;
+ }
+
+ // Memory Access
+
+ public Func ReadMemory;
+ public Action WriteMemory;
+ public Func PeekMemory;
+ public Func DummyReadMemory;
+
+ // Special Function for Speed switching executed on a STOP
+ public Func SpeedFunc;
+
+ //this only calls when the first byte of an instruction is fetched.
+ public Action OnExecFetch;
+
+ public void UnregisterMemoryMapper()
+ {
+ ReadMemory = null;
+ ReadMemory = null;
+ PeekMemory = null;
+ DummyReadMemory = null;
+ }
+
+ public void SetCallbacks
+ (
+ Func ReadMemory,
+ Func DummyReadMemory,
+ Func PeekMemory,
+ Action WriteMemory
+ )
+ {
+ this.ReadMemory = ReadMemory;
+ this.DummyReadMemory = DummyReadMemory;
+ this.PeekMemory = PeekMemory;
+ this.WriteMemory = WriteMemory;
+ }
+
+ //a little CDL related stuff
+ public delegate void DoCDLCallbackType(ushort addr, MC6800.eCDLogMemFlags flags);
+
+ public DoCDLCallbackType CDLCallback;
+
+ public enum eCDLogMemFlags
+ {
+ FetchFirst = 1,
+ FetchOperand = 2,
+ Data = 4,
+ Write = 8
+ };
+
+ // Execute instructions
+ public void ExecuteOne()
+ {
+ //Console.Write(opcode_see + " ");
+ //Console.WriteLine(Regs[PC] + " ");
+ switch (cur_instr[instr_pntr++])
+ {
+ case IDLE:
+ // do nothing
+ break;
+ case OP:
+ // Read the opcode of the next instruction
+ if (OnExecFetch != null) OnExecFetch(PC);
+ if (TraceCallback != null) TraceCallback(State());
+ if (CDLCallback != null) CDLCallback(PC, eCDLogMemFlags.FetchFirst);
+ FetchInstruction(ReadMemory(Regs[PC]++));
+ instr_pntr = 0;
+ irq_pntr = -1;
+ break;
+ case RD:
+ Read_Func(cur_instr[instr_pntr++], cur_instr[instr_pntr++]);
+ break;
+ case RD_INC:
+ Read_Inc_Func(cur_instr[instr_pntr++], cur_instr[instr_pntr++]);
+ break;
+ case RD_INC_OP:
+ Read_Inc_Func(cur_instr[instr_pntr++], cur_instr[instr_pntr++]);
+ switch (cur_instr[instr_pntr++])
+ {
+ case AND8:
+ AND8_Func(cur_instr[instr_pntr++], cur_instr[instr_pntr++]);
+ break;
+ case ADD8:
+ ADD8_Func(cur_instr[instr_pntr++], cur_instr[instr_pntr++]);
+ break;
+ case ADC8:
+ ADC8_Func(cur_instr[instr_pntr++], cur_instr[instr_pntr++]);
+ break;
+ case OR8:
+ OR8_Func(cur_instr[instr_pntr++], cur_instr[instr_pntr++]);
+ break;
+ case XOR8:
+ XOR8_Func(cur_instr[instr_pntr++], cur_instr[instr_pntr++]);
+ break;
+ case BIT:
+ BIT_Func(cur_instr[instr_pntr++], cur_instr[instr_pntr++]);
+ break;
+ case SUB8:
+ SUB8_Func(cur_instr[instr_pntr++], cur_instr[instr_pntr++]);
+ break;
+ case SBC8:
+ SBC8_Func(cur_instr[instr_pntr++], cur_instr[instr_pntr++]);
+ break;
+ case CMP8:
+ CMP8_Func(cur_instr[instr_pntr++], cur_instr[instr_pntr++]);
+ break;
+ case DEC16:
+ DEC16_Func(cur_instr[instr_pntr++]);
+ break;
+ case ADD8BR:
+ ADD8BR_Func(cur_instr[instr_pntr++], cur_instr[instr_pntr++]);
+ break;
+ case TR:
+ TR_Func(cur_instr[instr_pntr++], cur_instr[instr_pntr++]);
+ break;
+ case SET_ADDR:
+ reg_d_ad = cur_instr[instr_pntr++];
+ reg_h_ad = cur_instr[instr_pntr++];
+ reg_l_ad = cur_instr[instr_pntr++];
+
+ Regs[reg_d_ad] = (ushort)((Regs[reg_h_ad] << 8) | Regs[reg_l_ad]);
+ break;
+ case JPE:
+ if (!FlagE) { instr_pntr = 44; irq_pntr = 10; };
+ break;
+ case IDX_DCDE:
+ Index_decode();
+ break;
+ case IDX_OP_BLD:
+ Index_Op_Builder();
+ break;
+ case EA_8:
+ Regs[IDX_EA] = (ushort)(Regs[indexed_reg] + (((Regs[ALU2] & 0x80) == 0x80) ? (Regs[ALU2] | 0xFF00) : Regs[ALU2]));
+ Index_Op_Builder();
+ break;
+ case LD_8:
+ LD_8_Func(cur_instr[instr_pntr++], cur_instr[instr_pntr++]);
+ break;
+ case LD_16:
+ LD_16_Func(cur_instr[instr_pntr++], cur_instr[instr_pntr++], cur_instr[instr_pntr++]);
+ break;
+ case LEA:
+ LEA_Func(cur_instr[instr_pntr++], cur_instr[instr_pntr++]);
+ break;
+ case ANDCC:
+ Regs[CC] &= Regs[instr_pntr++];
+ break;
+ }
+ break;
+ case WR:
+ Write_Func(cur_instr[instr_pntr++], cur_instr[instr_pntr++]);
+ break;
+ case WR_DEC_LO:
+ Write_Dec_Lo_Func(cur_instr[instr_pntr++], cur_instr[instr_pntr++]);
+ break;
+ case WR_DEC_HI:
+ Write_Dec_HI_Func(cur_instr[instr_pntr++], cur_instr[instr_pntr++]);
+ break;
+ case WR_DEC_LO_OP:
+ Write_Dec_Lo_Func(cur_instr[instr_pntr++], cur_instr[instr_pntr++]);
+ instr_pntr++;
+ break;
+ case WR_DEC_HI_OP:
+ Write_Dec_HI_Func(cur_instr[instr_pntr++], cur_instr[instr_pntr++]);
+ instr_pntr++;
+ break;
+ case WR_HI:
+ Write_Hi_Func(cur_instr[instr_pntr++], cur_instr[instr_pntr++]);
+ break;
+ case WR_HI_INC:
+ Write_Hi_Inc_Func(cur_instr[instr_pntr++], cur_instr[instr_pntr++]);
+ break;
+ case TR:
+ TR_Func(cur_instr[instr_pntr++], cur_instr[instr_pntr++]);
+ break;
+ case LD_8:
+ LD_8_Func(cur_instr[instr_pntr++], cur_instr[instr_pntr++]);
+ break;
+ case LD_16:
+ LD_16_Func(cur_instr[instr_pntr++], cur_instr[instr_pntr++], cur_instr[instr_pntr++]);
+ break;
+ case LEA:
+ LEA_Func(cur_instr[instr_pntr++], cur_instr[instr_pntr++]);
+ break;
+ case EXG:
+ EXG_Func(cur_instr[instr_pntr++]);
+ break;
+ case IDX_OP_BLD:
+ Index_Op_Builder();
+ break;
+ case EA_16:
+ Regs[IDX_EA] = (ushort)(Regs[indexed_reg] + Regs[ADDR]);
+ Index_Op_Builder();
+ break;
+ case TFR:
+ TFR_Func(cur_instr[instr_pntr++]);
+ break;
+ case SET_ADDR:
+ reg_d_ad = cur_instr[instr_pntr++];
+ reg_h_ad = cur_instr[instr_pntr++];
+ reg_l_ad = cur_instr[instr_pntr++];
+
+ // Console.WriteLine(reg_d_ad + " " + reg_h_ad + " " + reg_l_ad);
+ // Console.WriteLine(Regs[reg_d_ad] + " " + Regs[reg_h_ad] + " " + Regs[reg_l_ad]);
+
+ Regs[reg_d_ad] = (ushort)((Regs[reg_h_ad] << 8) | Regs[reg_l_ad]);
+ break;
+ case NEG:
+ NEG_8_Func(cur_instr[instr_pntr++]);
+ break;
+ case TST:
+ TST_Func(cur_instr[instr_pntr++]);
+ break;
+ case CLR:
+ CLR_Func(cur_instr[instr_pntr++]);
+ break;
+ case SEX:
+ SEX_Func(cur_instr[instr_pntr++]);
+ break;
+ case ABX:
+ Regs[X] += Regs[B];
+ break;
+ case MUL:
+ Mul_Func();
+ break;
+ case SET_F_I:
+ FlagI = true; FlagF = true;
+ break;
+ case SET_I:
+ FlagI = true;
+ break;
+ case SET_E:
+ FlagE = true;
+ break;
+ case CLR_E:
+ FlagE = false;
+ break;
+ case ANDCC:
+ Regs[CC] &= Regs[instr_pntr++];
+ break;
+ case ADD16BR:
+ ADD16BR_Func(cur_instr[instr_pntr++], cur_instr[instr_pntr++]);
+ break;
+ case ADD8BR:
+ ADD8BR_Func(cur_instr[instr_pntr++], cur_instr[instr_pntr++]);
+ break;
+ case ADD8:
+ ADD8_Func(cur_instr[instr_pntr++], cur_instr[instr_pntr++]);
+ break;
+ case SUB8:
+ SUB8_Func(cur_instr[instr_pntr++], cur_instr[instr_pntr++]);
+ break;
+ case ADC8:
+ ADC8_Func(cur_instr[instr_pntr++], cur_instr[instr_pntr++]);
+ break;
+ case SBC8:
+ SBC8_Func(cur_instr[instr_pntr++], cur_instr[instr_pntr++]);
+ break;
+ case CMP8:
+ CMP8_Func(cur_instr[instr_pntr++], cur_instr[instr_pntr++]);
+ break;
+ case INC16:
+ INC16_Func(cur_instr[instr_pntr++]);
+ break;
+ case INC8:
+ INC8_Func(cur_instr[instr_pntr++]);
+ break;
+ case DEC16:
+ DEC16_Func(cur_instr[instr_pntr++]);
+ break;
+ case SUB16:
+ SUB16_Func(cur_instr[instr_pntr++]);
+ break;
+ case ADD16:
+ ADD16_Func(cur_instr[instr_pntr++]);
+ break;
+ case CMP16:
+ CMP16_Func(cur_instr[instr_pntr++], cur_instr[instr_pntr++]);
+ break;
+ case CMP16D:
+ CMP16D_Func(cur_instr[instr_pntr++]);
+ break;
+ case DEC8:
+ DEC8_Func(cur_instr[instr_pntr++]);
+ break;
+ case ROL:
+ ROL_Func(cur_instr[instr_pntr++]);
+ break;
+ case ROR:
+ ROR_Func(cur_instr[instr_pntr++]);
+ break;
+ case COM:
+ COM_Func(cur_instr[instr_pntr++]);
+ break;
+ case DA:
+ DA_Func(cur_instr[instr_pntr++]);
+ break;
+ case AND8:
+ AND8_Func(cur_instr[instr_pntr++], cur_instr[instr_pntr++]);
+ break;
+ case XOR8:
+ XOR8_Func(cur_instr[instr_pntr++], cur_instr[instr_pntr++]);
+ break;
+ case OR8:
+ OR8_Func(cur_instr[instr_pntr++], cur_instr[instr_pntr++]);
+ break;
+ case ASL:
+ ASL_Func(cur_instr[instr_pntr++]);
+ break;
+ case ASR:
+ ASR_Func(cur_instr[instr_pntr++]);
+ break;
+ case LSR:
+ LSR_Func(cur_instr[instr_pntr++]);
+ break;
+ case TAP:
+ instr_pntr++;
+ Regs[CC] = (ushort)((Regs[A] & 0x3F) | 0xC0); // last 2 bits always 1
+ break;
+ case TPA:
+ instr_pntr++;
+ Regs[A] = Regs[CC];
+ break;
+ case INX:
+ instr_pntr++;
+ Regs[X] = (ushort)(Regs[X] + 1);
+ FlagZ = Regs[X] == 0;
+ break;
+ case DEX:
+ instr_pntr++;
+ Regs[X] = (ushort)(Regs[X] - 1);
+ FlagZ = Regs[X] == 0;
+ break;
+ case CLV:
+ instr_pntr++;
+ FlagV = false;
+ break;
+ case SEV:
+ instr_pntr++;
+ FlagV = true;
+ break;
+ case CLC:
+ instr_pntr++;
+ FlagC = false;
+ break;
+ case SEC:
+ instr_pntr++;
+ FlagC = true;
+ break;
+ case CLI:
+ instr_pntr++;
+ FlagI = false;
+ break;
+ case SEI:
+ instr_pntr++;
+ FlagI = true;
+ break;
+ case BIT:
+ BIT_Func(cur_instr[instr_pntr++], cur_instr[instr_pntr++]);
+ break;
+ case CWAI:
+ if (NMIPending)
+ {
+ NMIPending = false;
+
+ Regs[ADDR] = 0xFFFC;
+ PopulateCURINSTR(RD_INC, ALU, ADDR,
+ RD_INC, ALU2, ADDR,
+ SET_ADDR, PC, ALU, ALU2);
+ irq_pntr = -1;
+ IRQS = 3;
+
+ if (TraceCallback != null) { TraceCallback(new TraceInfo { Disassembly = "====CWAI NMI====", RegisterInfo = "" }); }
+ }
+ else if (FIRQPending && !FlagF)
+ {
+ FIRQPending = false;
+
+ Regs[ADDR] = 0xFFF6;
+ PopulateCURINSTR(RD_INC, ALU, ADDR,
+ RD_INC, ALU2, ADDR,
+ SET_ADDR, PC, ALU, ALU2);
+ irq_pntr = -1;
+ IRQS = 3;
+
+ if (TraceCallback != null) { TraceCallback(new TraceInfo { Disassembly = "====CWAI FIRQ====", RegisterInfo = "" }); }
+ }
+ else if (IRQPending && !FlagI)
+ {
+ IRQPending = false;
+
+ Regs[ADDR] = 0xFFF8;
+ PopulateCURINSTR(RD_INC, ALU, ADDR,
+ RD_INC, ALU2, ADDR,
+ SET_ADDR, PC, ALU, ALU2);
+ irq_pntr = -1;
+ IRQS = 3;
+
+ if (TraceCallback != null) { TraceCallback(new TraceInfo { Disassembly = "====CWAI IRQ====", RegisterInfo = "" }); }
+ }
+ else
+ {
+ PopulateCURINSTR(CWAI);
+ irq_pntr = 0;
+ IRQS = -1;
+ }
+ instr_pntr = 0;
+ break;
+ case SYNC:
+ IN_SYNC = true;
+ IRQS = 1;
+ instr_pntr = irq_pntr = 0;
+ PopulateCURINSTR(SYNC);
+ break;
+ }
+
+ if (++irq_pntr == IRQS)
+ {
+ // NMI has priority
+ if (NMIPending)
+ {
+ NMIPending = false;
+
+ if (TraceCallback != null) { TraceCallback(new TraceInfo { Disassembly = "====NMI====", RegisterInfo = "" }); }
+
+ IN_SYNC = false;
+ NMI_();
+ NMICallback();
+ instr_pntr = irq_pntr = 0;
+ }
+ // fast IRQ has next priority
+ else if (FIRQPending)
+ {
+ if (!FlagF)
+ {
+ FIRQPending = false;
+
+ if (TraceCallback != null) { TraceCallback(new TraceInfo { Disassembly = "====FIRQ====", RegisterInfo = "" }); }
+
+ IN_SYNC = false;
+ FIRQ_();
+ FIRQCallback();
+ instr_pntr = irq_pntr = 0;
+ }
+ else if (IN_SYNC)
+ {
+ FIRQPending = false;
+
+ if (TraceCallback != null) { TraceCallback(new TraceInfo { Disassembly = "====SYNC====", RegisterInfo = "" }); }
+
+ IN_SYNC = false;
+ IRQS = 1;
+ instr_pntr = irq_pntr = 0;
+ PopulateCURINSTR(IDLE);
+ }
+ }
+ // then regular IRQ
+ else if (IRQPending && !FlagI)
+ {
+ if (!FlagI)
+ {
+ IRQPending = false;
+
+ if (TraceCallback != null) { TraceCallback(new TraceInfo { Disassembly = "====IRQ====", RegisterInfo = "" }); }
+
+ IN_SYNC = false;
+ IRQ_();
+ IRQCallback();
+ instr_pntr = irq_pntr = 0;
+ }
+ else if (IN_SYNC)
+ {
+ IRQPending = false;
+
+ if (TraceCallback != null) { TraceCallback(new TraceInfo { Disassembly = "====SYNC====", RegisterInfo = "" }); }
+
+ IN_SYNC = false;
+ IRQS = 1;
+ instr_pntr = irq_pntr = 0;
+ PopulateCURINSTR(IDLE);
+ }
+ }
+ // otherwise start the next instruction
+ else
+ {
+ PopulateCURINSTR(OP);
+ instr_pntr = irq_pntr = 0;
+ IRQS = -1;
+ }
+ }
+
+ TotalExecutedCycles++;
+ }
+
+ // tracer stuff
+
+ public Action TraceCallback;
+
+ public string TraceHeader
+ {
+ get { return "MC6809: PC, machine code, mnemonic, operands, registers (A, B, X, Y, US, SP, DP, CC), Cy, flags (EFHINZVC)"; }
+ }
+
+ public TraceInfo State(bool disassemble = true)
+ {
+ ushort notused;
+
+ return new TraceInfo
+ {
+ Disassembly = $"{(disassemble ? Disassemble(Regs[PC], ReadMemory, out notused) : "---")} ".PadRight(50),
+ RegisterInfo = string.Format(
+ "A:{0:X2} B:{1:X2} X:{2:X4} SP:{3:X4} DP:{4:X2} CC:{5:X2} Cy:{6} {7}{8}{9}{10}{11}{12}{13}{14}",
+ Regs[A],
+ Regs[B],
+ Regs[X],
+ Regs[SP],
+ Regs[DP],
+ Regs[CC],
+ TotalExecutedCycles,
+ FlagE ? "E" : "e",
+ FlagF ? "F" : "f",
+ FlagH ? "H" : "h",
+ FlagI ? "I" : "i",
+ FlagN ? "N" : "n",
+ FlagZ ? "Z" : "z",
+ FlagV ? "V" : "v",
+ FlagC ? "C" : "c"
+ )
+ };
+ }
+
+ ///
+ /// Optimization method to set cur_instr
+ ///
+ private void PopulateCURINSTR(ushort d0 = 0, ushort d1 = 0, ushort d2 = 0, ushort d3 = 0, ushort d4 = 0, ushort d5 = 0, ushort d6 = 0, ushort d7 = 0, ushort d8 = 0,
+ ushort d9 = 0, ushort d10 = 0, ushort d11 = 0, ushort d12 = 0, ushort d13 = 0, ushort d14 = 0, ushort d15 = 0, ushort d16 = 0, ushort d17 = 0, ushort d18 = 0,
+ ushort d19 = 0, ushort d20 = 0, ushort d21 = 0, ushort d22 = 0, ushort d23 = 0, ushort d24 = 0, ushort d25 = 0, ushort d26 = 0, ushort d27 = 0, ushort d28 = 0,
+ ushort d29 = 0, ushort d30 = 0, ushort d31 = 0, ushort d32 = 0, ushort d33 = 0, ushort d34 = 0, ushort d35 = 0, ushort d36 = 0, ushort d37 = 0, ushort d38 = 0,
+ ushort d39 = 0, ushort d40 = 0, ushort d41 = 0, ushort d42 = 0, ushort d43 = 0, ushort d44 = 0, ushort d45 = 0, ushort d46 = 0, ushort d47 = 0, ushort d48 = 0,
+ ushort d49 = 0, ushort d50 = 0, ushort d51 = 0, ushort d52 = 0, ushort d53 = 0, ushort d54 = 0, ushort d55 = 0, ushort d56 = 0, ushort d57 = 0, ushort d58 = 0)
+ {
+ cur_instr[0] = d0; cur_instr[1] = d1; cur_instr[2] = d2;
+ cur_instr[3] = d3; cur_instr[4] = d4; cur_instr[5] = d5;
+ cur_instr[6] = d6; cur_instr[7] = d7; cur_instr[8] = d8;
+ cur_instr[9] = d9; cur_instr[10] = d10; cur_instr[11] = d11;
+ cur_instr[12] = d12; cur_instr[13] = d13; cur_instr[14] = d14;
+ cur_instr[15] = d15; cur_instr[16] = d16; cur_instr[17] = d17;
+ cur_instr[18] = d18; cur_instr[19] = d19; cur_instr[20] = d20;
+ cur_instr[21] = d21; cur_instr[22] = d22; cur_instr[23] = d23;
+ cur_instr[24] = d24; cur_instr[25] = d25; cur_instr[26] = d26;
+ cur_instr[27] = d27; cur_instr[28] = d28; cur_instr[29] = d29;
+ cur_instr[30] = d30; cur_instr[31] = d31; cur_instr[32] = d32;
+ cur_instr[33] = d33; cur_instr[34] = d34; cur_instr[35] = d35;
+ cur_instr[36] = d36; cur_instr[37] = d37; cur_instr[38] = d38;
+ cur_instr[39] = d39; cur_instr[40] = d40; cur_instr[41] = d41;
+ cur_instr[42] = d42; cur_instr[43] = d43; cur_instr[44] = d44;
+ cur_instr[45] = d45; cur_instr[46] = d46; cur_instr[47] = d47;
+ cur_instr[48] = d48; cur_instr[49] = d49; cur_instr[50] = d50;
+ cur_instr[51] = d51; cur_instr[52] = d52; cur_instr[53] = d53;
+ cur_instr[54] = d54; cur_instr[55] = d55; cur_instr[56] = d56;
+ cur_instr[57] = d57; cur_instr[58] = d58;
+ }
+
+ // State Save/Load
+ public void SyncState(Serializer ser)
+ {
+ ser.BeginSection("MC6809");
+
+ ser.Sync(nameof(IN_SYNC), ref IN_SYNC);
+ ser.Sync(nameof(NMIPending), ref NMIPending);
+ ser.Sync(nameof(FIRQPending), ref FIRQPending);
+ ser.Sync(nameof(IRQPending), ref IRQPending);
+
+ ser.Sync(nameof(indexed_op), ref indexed_op);
+ ser.Sync(nameof(indexed_reg), ref indexed_reg);
+ ser.Sync(nameof(indexed_op_reg), ref indexed_op_reg);
+ ser.Sync(nameof(temp), ref temp);
+
+ ser.Sync(nameof(instr_pntr), ref instr_pntr);
+ ser.Sync(nameof(cur_instr), ref cur_instr, false);
+ ser.Sync(nameof(opcode_see), ref opcode_see);
+ ser.Sync(nameof(IRQS), ref IRQS);
+ ser.Sync(nameof(irq_pntr), ref irq_pntr);
+
+ ser.Sync(nameof(Regs), ref Regs, false);
+ ser.Sync(nameof(TotalExecutedCycles), ref TotalExecutedCycles);
+
+ ser.EndSection();
+ }
+ }
+}
diff --git a/BizHawk.Emulation.Cores/CPUs/MC6800/OP_Tables.cs b/BizHawk.Emulation.Cores/CPUs/MC6800/OP_Tables.cs
new file mode 100644
index 0000000000..cdcb3a829b
--- /dev/null
+++ b/BizHawk.Emulation.Cores/CPUs/MC6800/OP_Tables.cs
@@ -0,0 +1,528 @@
+using System;
+using BizHawk.Common.NumberExtensions;
+
+namespace BizHawk.Emulation.Common.Components.MC6800
+{
+ public partial class MC6800
+ {
+ // this contains the vectors of instrcution operations
+ // NOTE: This list is NOT confirmed accurate for each individual cycle
+
+ private void NOP_()
+ {
+ PopulateCURINSTR(IDLE);
+
+ IRQS = 1;
+ }
+
+ private void ILLEGAL()
+ {
+ //throw new Exception("Encountered illegal instruction");
+ PopulateCURINSTR(IDLE);
+
+ IRQS = 1;
+ }
+
+ private void SYNC_()
+ {
+ PopulateCURINSTR(IDLE,
+ SYNC);
+
+ IRQS = -1;
+ }
+
+ private void REG_OP(ushort oper, ushort src)
+ {
+ PopulateCURINSTR(oper, src);
+
+ IRQS = 1;
+ }
+
+ private void REG_OP_16(ushort oper, ushort src)
+ {
+ PopulateCURINSTR(IDLE,
+ IDLE,
+ oper, src);
+
+ IRQS = 3;
+ }
+
+ private void DIRECT_MEM(ushort oper)
+ {
+ PopulateCURINSTR(RD_INC, ALU, PC,
+ SET_ADDR, ADDR, DP, ALU,
+ RD, ALU, ADDR,
+ oper, ALU,
+ WR, ADDR, ALU);
+
+ IRQS = 5;
+ }
+
+ private void DIRECT_ST_4(ushort dest)
+ {
+ PopulateCURINSTR(RD_INC_OP, ALU, PC, SET_ADDR, ADDR, DP, ALU,
+ IDLE,
+ WR, ADDR, dest);
+
+ IRQS = 3;
+ }
+
+ private void DIRECT_MEM_4(ushort oper, ushort dest)
+ {
+ PopulateCURINSTR(RD_INC_OP, ALU, PC, SET_ADDR, ADDR, DP, ALU,
+ IDLE,
+ RD_INC_OP, ALU, ADDR, oper, dest, ALU);
+
+ IRQS = 3;
+ }
+
+ private void EXT_MEM(ushort oper)
+ {
+ PopulateCURINSTR(RD_INC, ALU, PC,
+ RD_INC, ALU2, PC,
+ SET_ADDR, ADDR, ALU, ALU2,
+ RD, ALU, ADDR,
+ oper, ALU,
+ WR, ADDR, ALU);
+
+ IRQS = 6;
+ }
+
+ private void EXT_REG(ushort oper, ushort dest)
+ {
+ PopulateCURINSTR(RD_INC, ALU, PC,
+ RD_INC_OP, ALU2, PC, SET_ADDR, ADDR, ALU, ALU2,
+ RD, ALU, ADDR,
+ oper, dest, ALU);
+
+ IRQS = 4;
+ }
+
+ private void EXT_ST(ushort dest)
+ {
+ PopulateCURINSTR(RD_INC, ALU, PC,
+ RD_INC_OP, ALU2, PC, SET_ADDR, ADDR, ALU, ALU2,
+ IDLE,
+ WR, ADDR, dest);
+
+ IRQS = 4;
+ }
+
+ private void REG_OP_IMD_CC(ushort oper)
+ {
+ Regs[ALU2] = Regs[CC];
+ PopulateCURINSTR(RD_INC_OP, ALU, PC, oper, ALU2, ALU,
+ TR, CC, ALU2);
+
+ IRQS = 2;
+ }
+
+ private void REG_OP_IMD(ushort oper, ushort dest)
+ {
+ PopulateCURINSTR(RD_INC_OP, ALU, PC, oper, dest, ALU);
+
+ IRQS = 1;
+ }
+
+ private void IMD_OP_D(ushort oper, ushort dest)
+ {
+ PopulateCURINSTR(RD_INC, ALU, PC,
+ RD_INC_OP, ALU2, PC, SET_ADDR, ADDR, ALU, ALU2,
+ oper, ADDR);
+
+ IRQS = 3;
+ }
+
+ private void DIR_OP_D(ushort oper, ushort dest)
+ {
+ PopulateCURINSTR(RD_INC_OP, ALU, PC, SET_ADDR, ADDR, DP, ALU,
+ RD_INC, ALU, ADDR,
+ RD, ALU2, ADDR,
+ SET_ADDR, ADDR, ALU, ALU2,
+ oper, ADDR);
+
+ IRQS = 5;
+ }
+
+ private void EXT_OP_D(ushort oper, ushort dest)
+ {
+ PopulateCURINSTR(RD_INC, ALU, PC,
+ RD_INC_OP, ALU2, PC, SET_ADDR, ADDR, ALU, ALU2,
+ RD_INC, ALU, ADDR,
+ RD, ALU2, ADDR,
+ SET_ADDR, ADDR, ALU, ALU2,
+ oper, ADDR);
+
+ IRQS = 6;
+ }
+
+ private void REG_OP_LD_16D()
+ {
+ PopulateCURINSTR(RD_INC, A, PC,
+ RD_INC_OP, B, PC, LD_16, ADDR, A, B);
+
+ IRQS = 2;
+ }
+
+ private void DIR_OP_LD_16D()
+ {
+ PopulateCURINSTR(RD_INC_OP, ALU, PC, SET_ADDR, ADDR, DP, ALU,
+ IDLE,
+ RD_INC, A, ADDR,
+ RD_INC_OP, B, ADDR, LD_16, ADDR, A, B);
+
+ IRQS = 4;
+ }
+
+ private void DIR_OP_ST_16D()
+ {
+ PopulateCURINSTR(RD_INC_OP, ALU, PC, SET_ADDR, ADDR, DP, ALU,
+ SET_ADDR, ALU, A, A,
+ WR_HI_INC, ADDR, ALU,
+ WR, ADDR, B);
+
+ IRQS = 4;
+ }
+
+ private void DIR_CMP_16(ushort oper, ushort dest)
+ {
+ PopulateCURINSTR(RD_INC_OP, ALU, PC, SET_ADDR, ADDR, DP, ALU,
+ RD_INC, ALU, ADDR,
+ RD, ALU2, ADDR,
+ SET_ADDR, ADDR, ALU, ALU2,
+ oper, dest, ADDR);
+
+ IRQS = 5;
+ }
+
+ private void IMD_CMP_16(ushort oper, ushort dest)
+ {
+ PopulateCURINSTR(RD_INC, ALU, PC,
+ RD_INC_OP, ALU2, PC, SET_ADDR, ADDR, ALU, ALU2,
+ oper, dest, ADDR);
+
+ IRQS = 3;
+ }
+
+ private void REG_OP_LD_16(ushort dest)
+ {
+ PopulateCURINSTR(RD_INC, ALU, PC,
+ RD_INC_OP, ALU2, PC, LD_16, dest, ALU, ALU2);
+
+ IRQS = 2;
+ }
+
+ private void DIR_OP_LD_16(ushort dest)
+ {
+ PopulateCURINSTR(RD_INC_OP, ALU, PC, SET_ADDR, ADDR, DP, ALU,
+ IDLE,
+ RD_INC, ALU, ADDR,
+ RD_INC_OP, ALU2, ADDR, LD_16, dest, ALU, ALU2);
+
+ IRQS = 4;
+ }
+
+ private void DIR_OP_ST_16(ushort src)
+ {
+ PopulateCURINSTR(RD_INC_OP, ALU, PC, SET_ADDR, ADDR, DP, ALU,
+ IDLE,
+ WR_HI_INC, ADDR, src,
+ WR_DEC_LO, ADDR, src);
+
+ IRQS = 4;
+ }
+
+ private void EXT_OP_LD_16(ushort dest)
+ {
+ PopulateCURINSTR(RD_INC, ALU, PC,
+ RD_INC_OP, ALU2, PC, SET_ADDR, ADDR, ALU, ALU2,
+ IDLE,
+ RD_INC, ALU, ADDR,
+ RD_INC_OP, ALU2, ADDR, LD_16, dest, ALU, ALU2);
+
+ IRQS = 5;
+ }
+
+ private void EXT_OP_ST_16(ushort src)
+ {
+ PopulateCURINSTR(RD_INC, ALU, PC,
+ RD_INC_OP, ALU2, PC, SET_ADDR, ADDR, ALU, ALU2,
+ IDLE,
+ WR_HI_INC, ADDR, src,
+ WR_DEC_LO, ADDR, src);
+
+ IRQS = 5;
+ }
+
+ private void EXT_OP_LD_16D()
+ {
+ PopulateCURINSTR(RD_INC, ALU, PC,
+ RD_INC_OP, ALU2, PC, SET_ADDR, ADDR, ALU, ALU2,
+ IDLE,
+ RD_INC, A, ADDR,
+ RD_INC_OP, B, ADDR, LD_16, ADDR, A, B);
+
+ IRQS = 5;
+ }
+
+ private void EXT_OP_ST_16D()
+ {
+ PopulateCURINSTR(RD_INC, ALU, PC,
+ RD_INC_OP, ALU2, PC, SET_ADDR, ADDR, ALU, ALU2,
+ SET_ADDR, ALU, A, A,
+ WR_HI_INC, ADDR, ALU,
+ WR, ADDR, B);
+
+ IRQS = 5;
+ }
+
+ private void EXT_CMP_16(ushort oper, ushort dest)
+ {
+ PopulateCURINSTR(RD_INC, ALU, PC,
+ RD_INC_OP, ALU2, PC, SET_ADDR, ADDR, ALU, ALU2,
+ RD_INC, ALU, ADDR,
+ RD, ALU2, ADDR,
+ SET_ADDR, ADDR, ALU, ALU2,
+ oper, dest, ADDR);
+
+ IRQS = 6;
+ }
+
+ private void EXG_()
+ {
+ PopulateCURINSTR(RD_INC, ALU, PC,
+ EXG, ALU,
+ IDLE,
+ IDLE,
+ IDLE,
+ IDLE,
+ IDLE);
+
+ IRQS = 7;
+ }
+
+ private void TFR_()
+ {
+ PopulateCURINSTR(RD_INC, ALU, PC,
+ TFR, ALU,
+ IDLE,
+ IDLE,
+ IDLE);
+
+ IRQS = 5;
+ }
+
+ private void JMP_DIR_()
+ {
+ PopulateCURINSTR(RD_INC, ALU, PC,
+ SET_ADDR, PC, DP, ALU);
+
+ IRQS = 2;
+ }
+
+ private void JMP_EXT_()
+ {
+ PopulateCURINSTR(RD_INC, ALU, PC,
+ RD_INC, ALU2, PC,
+ SET_ADDR, PC, ALU, ALU2);
+
+ IRQS = 3;
+ }
+
+ private void JSR_()
+ {
+ PopulateCURINSTR(RD_INC, ALU, PC,
+ SET_ADDR, ADDR, DP, ALU,
+ DEC16, SP,
+ TR, PC, ADDR,
+ WR_DEC_LO, SP, ADDR,
+ WR_HI, SP, ADDR);
+
+ IRQS = 6;
+ }
+
+ private void JSR_EXT()
+ {
+ PopulateCURINSTR(RD_INC, ALU, PC,
+ RD_INC_OP, ALU2, PC, SET_ADDR, ADDR, ALU, ALU2,
+ TR, ALU, PC,
+ DEC16, SP,
+ TR, PC, ADDR,
+ WR_DEC_LO, SP, ALU,
+ WR_HI, SP, ALU);
+
+ IRQS = 7;
+ }
+
+ private void LBR_(bool cond)
+ {
+ if (cond)
+ {
+ PopulateCURINSTR(RD_INC, ALU, PC,
+ RD_INC, ALU2, PC,
+ SET_ADDR, ADDR, ALU, ALU2,
+ ADD16BR, PC, ADDR);
+
+ IRQS = 4;
+ }
+ else
+ {
+ PopulateCURINSTR(RD_INC, ALU, PC,
+ RD_INC, ALU2, PC,
+ SET_ADDR, ADDR, ALU, ALU2);
+
+ IRQS = 3;
+ }
+ }
+
+ private void BR_(bool cond)
+ {
+ if (cond)
+ {
+ PopulateCURINSTR(RD_INC, ALU, PC,
+ ADD8BR, PC, ALU);
+
+ IRQS = 2;
+ }
+ else
+ {
+ PopulateCURINSTR(RD_INC, ALU, PC,
+ IDLE);
+
+ IRQS = 2;
+ }
+ }
+
+ private void BSR_()
+ {
+ PopulateCURINSTR(RD_INC, ALU, PC,
+ TR, ADDR, PC,
+ ADD8BR, PC, ALU,
+ DEC16, SP,
+ WR_DEC_LO, SP, ADDR,
+ WR_HI, SP, ADDR);
+
+ IRQS = 6;
+ }
+
+ private void LBSR_()
+ {
+ PopulateCURINSTR(RD_INC, ALU, PC,
+ RD_INC, ALU2, PC,
+ SET_ADDR, ADDR, ALU, ALU2,
+ TR, ALU, PC,
+ ADD16BR, PC, ADDR,
+ DEC16, SP,
+ WR_DEC_LO, SP, ALU,
+ WR_HI, SP, ALU);
+
+ IRQS = 8;
+ }
+
+ private void ABX_()
+ {
+ PopulateCURINSTR(ABX,
+ IDLE);
+
+ IRQS = 2;
+ }
+
+ private void MUL_()
+ {
+ PopulateCURINSTR(MUL,
+ IDLE,
+ IDLE,
+ IDLE,
+ IDLE,
+ IDLE,
+ IDLE,
+ IDLE,
+ IDLE,
+ IDLE);
+
+ IRQS = 10;
+ }
+
+ private void RTS()
+ {
+ PopulateCURINSTR(IDLE,
+ RD_INC, ALU, SP,
+ RD_INC, ALU2, SP,
+ SET_ADDR, PC, ALU, ALU2);
+
+ IRQS = 4;
+ }
+
+ private void RTI()
+ {
+ PopulateCURINSTR(IDLE,
+ RD_INC_OP, CC, SP, JPE,
+ RD_INC, A, SP,
+ RD_INC, B, SP,
+ RD_INC, DP, SP,
+ RD_INC, ALU, SP,
+ RD_INC_OP, ALU2, SP, SET_ADDR, X, ALU, ALU2,
+ RD_INC, ALU, SP,
+ RD_INC_OP, ALU2, SP, SET_ADDR, PC, ALU, ALU2);
+
+ IRQS = 14;
+ }
+
+ private void PSH_(ushort src)
+ {
+ PopulateCURINSTR(WR, SP, src,
+ IDLE,
+ DEC16, SP);
+
+ IRQS = 3;
+ }
+
+ private void PUL_(ushort src)
+ {
+ PopulateCURINSTR(INC16, SP,
+ IDLE,
+ RD, src, SP);
+
+ IRQS = 3;
+ }
+
+ private void SWI1()
+ {
+ Regs[ADDR] = 0xFFFA;
+ PopulateCURINSTR(SET_E,
+ DEC16, SP,
+ WR_DEC_LO, SP, PC,
+ WR_DEC_HI, SP, PC,
+ WR_DEC_LO, SP, X,
+ WR_DEC_HI, SP, X,
+ WR_DEC_LO, SP, DP,
+ WR_DEC_LO, SP, B,
+ WR_DEC_LO, SP, A,
+ WR, SP, CC,
+ SET_F_I,
+ RD_INC, ALU, ADDR,
+ RD_INC, ALU2, ADDR,
+ SET_ADDR, PC, ALU, ALU2);
+
+ IRQS = 18;
+ }
+
+ private void CWAI_()
+ {
+ PopulateCURINSTR(RD_INC_OP, ALU, PC, ANDCC, ALU,
+ SET_E,
+ DEC16, SP,
+ WR_DEC_LO, SP, PC,
+ WR_DEC_HI, SP, PC,
+ WR_DEC_LO, SP, X,
+ WR_DEC_HI, SP, X,
+ WR_DEC_LO, SP, DP,
+ WR_DEC_LO, SP, B,
+ WR_DEC_LO, SP, A,
+ WR, SP, CC,
+ CWAI);
+
+ IRQS = 16;
+ }
+ }
+}
diff --git a/BizHawk.Emulation.Cores/CPUs/MC6800/Operations.cs b/BizHawk.Emulation.Cores/CPUs/MC6800/Operations.cs
new file mode 100644
index 0000000000..f5e6ba2080
--- /dev/null
+++ b/BizHawk.Emulation.Cores/CPUs/MC6800/Operations.cs
@@ -0,0 +1,666 @@
+using System;
+using BizHawk.Common.NumberExtensions;
+
+namespace BizHawk.Emulation.Common.Components.MC6800
+{
+ public partial class MC6800
+ {
+ public void Read_Func(ushort dest, ushort src)
+ {
+ if (CDLCallback != null)
+ {
+ if (src == PC) CDLCallback(Regs[src], eCDLogMemFlags.FetchOperand);
+ else CDLCallback(Regs[src], eCDLogMemFlags.Data);
+ }
+ Regs[dest] = ReadMemory(Regs[src]);
+ }
+
+ public void Read_Inc_Func(ushort dest, ushort src)
+ {
+ if (CDLCallback != null)
+ {
+ if (src == PC) CDLCallback(Regs[src], eCDLogMemFlags.FetchOperand);
+ else CDLCallback(Regs[src], eCDLogMemFlags.Data);
+ }
+ //Console.WriteLine(dest + " " + src + " " + opcode_see);
+
+ Regs[dest] = ReadMemory(Regs[src]);
+
+ Regs[src]++;
+ }
+
+ public void Write_Func(ushort dest, ushort src)
+ {
+ if (CDLCallback != null) CDLCallback(Regs[dest], eCDLogMemFlags.Write | eCDLogMemFlags.Data);
+ WriteMemory(Regs[dest], (byte)Regs[src]);
+ }
+
+ public void Write_Dec_Lo_Func(ushort dest, ushort src)
+ {
+ if (CDLCallback != null) CDLCallback(Regs[dest], eCDLogMemFlags.Write | eCDLogMemFlags.Data);
+ WriteMemory(Regs[dest], (byte)Regs[src]);
+ Regs[dest] -= 1;
+ }
+
+ public void Write_Dec_HI_Func(ushort dest, ushort src)
+ {
+ if (CDLCallback != null) CDLCallback(Regs[dest], eCDLogMemFlags.Write | eCDLogMemFlags.Data);
+ WriteMemory(Regs[dest], (byte)(Regs[src] >> 8));
+ Regs[dest] -= 1;
+ }
+
+ public void Write_Hi_Func(ushort dest, ushort src)
+ {
+ if (CDLCallback != null) CDLCallback(Regs[dest], eCDLogMemFlags.Write | eCDLogMemFlags.Data);
+ WriteMemory(Regs[dest], (byte)(Regs[src] >> 8));
+ }
+
+ public void Write_Hi_Inc_Func(ushort dest, ushort src)
+ {
+ if (CDLCallback != null) CDLCallback(Regs[dest], eCDLogMemFlags.Write | eCDLogMemFlags.Data);
+ WriteMemory(Regs[dest], (byte)(Regs[src] >> 8));
+ Regs[dest]++;
+ }
+
+ public void NEG_8_Func(ushort src)
+ {
+ int Reg16_d = 0;
+ Reg16_d -= Regs[src];
+
+ FlagC = Regs[src] != 0x0;
+ FlagZ = (Reg16_d & 0xFF) == 0;
+ FlagV = Regs[src] == 0x80;
+ FlagN = (Reg16_d & 0xFF) > 127;
+
+ ushort ans = (ushort)(Reg16_d & 0xFF);
+ // redo for half carry flag
+ Reg16_d = 0;
+ Reg16_d -= (Regs[src] & 0xF);
+ FlagH = Reg16_d.Bit(4);
+ Regs[src] = ans;
+ }
+
+ public void TR_Func(ushort dest, ushort src)
+ {
+ Regs[dest] = Regs[src];
+ }
+
+ public void LD_8_Func(ushort dest, ushort src)
+ {
+ Regs[dest] = Regs[src];
+
+ FlagZ = (Regs[dest] & 0xFF) == 0;
+ FlagV = false;
+ FlagN = (Regs[dest] & 0xFF) > 127;
+ }
+
+ public void LD_16_Func(ushort dest, ushort src_h, ushort src_l)
+ {
+ Regs[dest] = (ushort)(Regs[src_h] << 8 | Regs[src_l]);
+
+ FlagZ = Regs[dest] == 0;
+ FlagV = false;
+ FlagN = Regs[dest] > 0x7FFF;
+ }
+
+ // for LEAX/Y, zero flag can be effected, but not for U/S
+ public void LEA_Func(ushort dest, ushort src)
+ {
+ Regs[dest] = Regs[src];
+
+ if (dest == X)
+ {
+ FlagZ = Regs[dest] == 0;
+ }
+ }
+
+ public void TST_Func(ushort src)
+ {
+ FlagZ = Regs[src] == 0;
+ FlagV = false;
+ FlagN = (Regs[src] & 0xFF) > 127;
+ }
+
+ public void CLR_Func(ushort src)
+ {
+ Regs[src] = 0;
+
+ FlagZ = true;
+ FlagV = false;
+ FlagC = false;
+ FlagN = false;
+ }
+
+ // source is considered a 16 bit signed value, used for long relative branch
+ // no flags used
+ public void ADD16BR_Func(ushort dest, ushort src)
+ {
+ Regs[dest] = (ushort)(Regs[dest] + (short)Regs[src]);
+ }
+
+ public void ADD8BR_Func(ushort dest, ushort src)
+ {
+ if (Regs[src] > 127) { Regs[src] |= 0xFF00; }
+ Regs[dest] = (ushort)(Regs[dest] + (short)Regs[src]);
+ }
+
+ public void Mul_Func()
+ {
+ Regs[ALU] = (ushort)(Regs[A] * Regs[B]);
+ D = Regs[ALU];
+ FlagC = Regs[A] > 127;
+ FlagZ = D == 0;
+ }
+
+ public void ADD8_Func(ushort dest, ushort src)
+ {
+ int Reg16_d = Regs[dest];
+ Reg16_d += Regs[src];
+
+ FlagC = Reg16_d.Bit(8);
+ FlagZ = (Reg16_d & 0xFF) == 0;
+
+ ushort ans = (ushort)(Reg16_d & 0xFF);
+
+ // redo for half carry flag
+ Reg16_d = Regs[dest] & 0xF;
+ Reg16_d += (Regs[src] & 0xF);
+
+ FlagH = Reg16_d.Bit(4);
+ FlagV = (Regs[dest].Bit(7) == Regs[src].Bit(7)) && (Regs[dest].Bit(7) != ans.Bit(7));
+ FlagN = ans > 127;
+
+ Regs[dest] = ans;
+ }
+
+ public void SUB8_Func(ushort dest, ushort src)
+ {
+ int Reg16_d = Regs[dest];
+ Reg16_d -= Regs[src];
+
+ FlagC = Reg16_d.Bit(8);
+ FlagZ = (Reg16_d & 0xFF) == 0;
+
+ ushort ans = (ushort)(Reg16_d & 0xFF);
+
+ // redo for half carry flag
+ Reg16_d = Regs[dest] & 0xF;
+ Reg16_d -= (Regs[src] & 0xF);
+
+ FlagH = Reg16_d.Bit(4);
+ FlagN = ans > 127;
+ FlagV = (Regs[dest].Bit(7) != Regs[src].Bit(7)) && (Regs[dest].Bit(7) != ans.Bit(7));
+
+ Regs[dest] = ans;
+ }
+
+ // same as SUB8 but result not stored
+ public void CMP8_Func(ushort dest, ushort src)
+ {
+ int Reg16_d = Regs[dest];
+ Reg16_d -= Regs[src];
+
+ FlagC = Reg16_d.Bit(8);
+ FlagZ = (Reg16_d & 0xFF) == 0;
+
+ ushort ans = (ushort)(Reg16_d & 0xFF);
+
+ // redo for half carry flag
+ Reg16_d = Regs[dest] & 0xF;
+ Reg16_d -= (Regs[src] & 0xF);
+
+ FlagH = Reg16_d.Bit(4);
+ FlagN = ans > 127;
+ FlagV = (Regs[dest].Bit(7) != Regs[src].Bit(7)) && (Regs[dest].Bit(7) != ans.Bit(7));
+ }
+
+ public void BIT_Func(ushort dest, ushort src)
+ {
+ ushort ans = (ushort)(Regs[dest] & Regs[src]);
+
+ FlagZ = ans == 0;
+ FlagV = false;
+ FlagN = ans > 127;
+ }
+
+ public void ASL_Func(ushort src)
+ {
+ FlagC = Regs[src].Bit(7);
+ FlagV = Regs[src].Bit(7) ^ Regs[src].Bit(6);
+
+ Regs[src] = (ushort)((Regs[src] << 1) & 0xFF);
+
+ FlagZ = Regs[src] == 0;
+ FlagH = false;
+ FlagN = (Regs[src] & 0xFF) > 127;
+
+ }
+
+ public void ASR_Func(ushort src)
+ {
+ FlagC = Regs[src].Bit(0);
+
+ ushort temp = (ushort)(Regs[src] & 0x80); // MSB doesn't change in this operation
+
+ Regs[src] = (ushort)((Regs[src] >> 1) | temp);
+
+ FlagZ = Regs[src] == 0;
+ FlagH = false;
+ FlagN = (Regs[src] & 0xFF) > 127;
+ }
+
+ public void LSR_Func(ushort src)
+ {
+ FlagC = Regs[src].Bit(0);
+
+ Regs[src] = (ushort)(Regs[src] >> 1);
+
+ FlagZ = Regs[src] == 0;
+ FlagN = false;
+ }
+
+ public void COM_Func(ushort src)
+ {
+ Regs[src] = (ushort)((~Regs[src]) & 0xFF);
+
+ FlagC = true;
+ FlagZ = Regs[src] == 0;
+ FlagV = false;
+ FlagN = (Regs[src] & 0xFF) > 127;
+ }
+
+ public void SEX_Func(ushort src)
+ {
+ if (Regs[B] > 127)
+ {
+ Regs[A] = 0xFF;
+ }
+ else
+ {
+ Regs[A] = 0;
+ }
+
+ FlagZ = D == 0;
+ FlagN = Regs[A] > 127;
+ }
+
+ public void AND8_Func(ushort dest, ushort src)
+ {
+ Regs[dest] = (ushort)(Regs[dest] & Regs[src]);
+
+ FlagZ = Regs[dest] == 0;
+ FlagV = false;
+ FlagN = Regs[dest] > 127;
+ }
+
+ public void OR8_Func(ushort dest, ushort src)
+ {
+ Regs[dest] = (ushort)(Regs[dest] | Regs[src]);
+
+ FlagZ = Regs[dest] == 0;
+ FlagV = false;
+ FlagN = Regs[dest] > 127;
+ }
+
+ public void XOR8_Func(ushort dest, ushort src)
+ {
+ Regs[dest] = (ushort)(Regs[dest] ^ Regs[src]);
+
+ FlagZ = Regs[dest] == 0;
+ FlagV = false;
+ FlagN = Regs[dest] > 127;
+ }
+
+ public void ROR_Func(ushort src)
+ {
+ ushort c = (ushort)(FlagC ? 0x80 : 0);
+
+ FlagC = Regs[src].Bit(0);
+
+ Regs[src] = (ushort)(c | (Regs[src] >> 1));
+
+ FlagZ = Regs[src] == 0;
+ FlagN = (Regs[src] & 0xFF) > 127;
+ }
+
+ public void ROL_Func(ushort src)
+ {
+ ushort c = (ushort)(FlagC ? 1 : 0);
+ FlagC = Regs[src].Bit(7);
+ FlagV = Regs[src].Bit(7) ^ Regs[src].Bit(6);
+
+
+ Regs[src] = (ushort)(((Regs[src] << 1) & 0xFF) | c);
+
+ FlagZ = Regs[src] == 0;
+ FlagN = (Regs[src] & 0xFF) > 127;
+ }
+
+ public void INC8_Func(ushort src)
+ {
+ FlagV = Regs[src] == 0x7F;
+
+ Regs[src] = (ushort)((Regs[src] + 1) & 0xFF);
+
+ FlagZ = Regs[src] == 0;
+ FlagN = (Regs[src] & 0xFF) > 127;
+ }
+
+ public void DEC8_Func(ushort src)
+ {
+ FlagV = Regs[src] == 0x80;
+
+ Regs[src] = (ushort)((Regs[src] - 1) & 0xFF);
+
+ FlagZ = Regs[src] == 0;
+ FlagN = (Regs[src] & 0xFF) > 127;
+ }
+
+ public void INC16_Func(ushort src)
+ {
+ Regs[src] += 1;
+ }
+
+ public void DEC16_Func(ushort src)
+ {
+ Regs[src] -= 1;
+ }
+
+ public void ADC8_Func(ushort dest, ushort src)
+ {
+ int Reg16_d = Regs[dest];
+ int c = FlagC ? 1 : 0;
+
+ Reg16_d += (Regs[src] + c);
+
+ FlagC = Reg16_d.Bit(8);
+ FlagZ = (Reg16_d & 0xFF) == 0;
+
+ ushort ans = (ushort)(Reg16_d & 0xFF);
+
+ // redo for half carry flag
+ Reg16_d = Regs[dest] & 0xF;
+ Reg16_d += ((Regs[src] & 0xF) + c);
+
+ FlagH = Reg16_d.Bit(4);
+ FlagV = (Regs[dest].Bit(7) == Regs[src].Bit(7)) && (Regs[dest].Bit(7) != ans.Bit(7));
+ FlagN = false;
+
+ Regs[dest] = ans;
+ }
+
+ public void SBC8_Func(ushort dest, ushort src)
+ {
+ int Reg16_d = Regs[dest];
+ int c = FlagC ? 1 : 0;
+
+ Reg16_d -= (Regs[src] + c);
+
+ FlagC = Reg16_d.Bit(8);
+ FlagZ = (Reg16_d & 0xFF) == 0;
+
+ ushort ans = (ushort)(Reg16_d & 0xFF);
+
+ // redo for half carry flag
+ Reg16_d = Regs[dest] & 0xF;
+ Reg16_d -= ((Regs[src] & 0xF) + c);
+
+ FlagH = Reg16_d.Bit(4);
+ FlagN = ans > 127;
+ FlagV = (Regs[dest].Bit(7) != Regs[src].Bit(7)) && (Regs[dest].Bit(7) != ans.Bit(7));
+
+ Regs[dest] = ans;
+ }
+
+ // DA code courtesy of AWJ: http://forums.nesdev.com/viewtopic.php?f=20&t=15944
+ public void DA_Func(ushort src)
+ {
+ byte a = (byte)Regs[src];
+
+ if (!FlagN)
+ { // after an addition, adjust if (half-)carry occurred or if result is out of bounds
+ if (FlagC || a > 0x99) { a += 0x60; FlagC = true; }
+ if (FlagH || (a & 0x0f) > 0x09) { a += 0x6; }
+ }
+ else
+ { // after a subtraction, only adjust if (half-)carry occurred
+ if (FlagC) { a -= 0x60; }
+ if (FlagH) { a -= 0x6; }
+ }
+
+ a &= 0xFF;
+
+ Regs[src] = a;
+
+ FlagZ = a == 0;
+ FlagH = false;
+ }
+
+ // D register implied
+ public void SUB16_Func(ushort src)
+ {
+ int Reg16_d = D;
+ int Reg16_s = Regs[src];
+
+ Reg16_d -= Reg16_s;
+
+ FlagC = Reg16_d.Bit(16);
+ FlagZ = (Reg16_d & 0xFFFF) == 0;
+
+ ushort ans = (ushort)(Reg16_d & 0xFFFF);
+
+ FlagN = ans > 0x7FFF;
+ FlagV = (D.Bit(15) != Regs[src].Bit(15)) && (D.Bit(15) != ans.Bit(15));
+
+ D = ans;
+ }
+
+ // D register implied
+ public void ADD16_Func(ushort src)
+ {
+ int Reg16_d = D;
+ int Reg16_s = Regs[src];
+
+ Reg16_d += Reg16_s;
+
+ FlagC = Reg16_d.Bit(16);
+ FlagZ = (Reg16_d & 0xFFFF) == 0;
+
+ ushort ans = (ushort)(Reg16_d & 0xFFFF);
+
+ FlagN = ans > 0x7FFF;
+ FlagV = (D.Bit(15) == Regs[src].Bit(15)) && (D.Bit(15) != ans.Bit(15));
+
+ D = ans;
+ }
+
+ // D register implied
+ public void CMP16D_Func(ushort src)
+ {
+ int Reg16_d = D;
+ int Reg16_s = Regs[src];
+
+ Reg16_d -= Reg16_s;
+
+ FlagC = Reg16_d.Bit(16);
+ FlagZ = (Reg16_d & 0xFFFF) == 0;
+
+ ushort ans = (ushort)(Reg16_d & 0xFFFF);
+
+ FlagN = ans > 0x7FFF;
+ FlagV = (D.Bit(15) != Regs[src].Bit(15)) && (D.Bit(15) != ans.Bit(15));
+ }
+
+ public void CMP16_Func(ushort dest, ushort src)
+ {
+ int Reg16_d = Regs[dest];
+ int Reg16_s = Regs[src];
+
+ Reg16_d -= Reg16_s;
+
+ FlagC = Reg16_d.Bit(16);
+ FlagZ = (Reg16_d & 0xFFFF) == 0;
+
+ ushort ans = (ushort)(Reg16_d & 0xFFFF);
+
+ FlagN = ans > 0x7FFF;
+ FlagV = (Regs[dest].Bit(15) != Regs[src].Bit(15)) && (Regs[dest].Bit(15) != ans.Bit(15));
+ }
+
+ public void EXG_Func(ushort sel)
+ {
+ ushort src = 0;
+ ushort dest = 0;
+ ushort temp = 0;
+ if ((Regs[sel] & 0x8) == 0)
+ {
+ switch (Regs[sel] & 0xF)
+ {
+ case 0: src = Dr; break;
+ case 1: src = X; break;
+
+ case 4: src = SP; break;
+ case 5: src = PC; break;
+ case 6: src = 0xFF; break;
+ case 7: src = 0xFF; break;
+ }
+
+ switch ((Regs[sel] >> 4) & 0xF)
+ {
+ case 0: dest = Dr; break;
+ case 1: dest = X; break;
+
+ case 4: dest = SP; break;
+ case 5: dest = PC; break;
+ case 6: dest = 0xFF; break;
+ case 7: dest = 0xFF; break;
+ default: dest = 0xFF; break;
+ }
+ }
+ else
+ {
+ switch (Regs[sel] & 0xF)
+ {
+ case 8: src = A; break;
+ case 9: src = B; break;
+ case 10: src = CC; break;
+ case 11: src = DP; break;
+ case 12: src = 0xFF; break;
+ case 13: src = 0xFF; break;
+ case 14: src = 0xFF; break;
+ case 15: src = 0xFF; break;
+ }
+
+ switch ((Regs[sel] >> 4) & 0xF)
+ {
+ case 8: dest = A; break;
+ case 9: dest = B; break;
+ case 10: dest = CC; break;
+ case 11: dest = DP; break;
+ case 12: dest = 0xFF; break;
+ case 13: dest = 0xFF; break;
+ case 14: dest = 0xFF; break;
+ case 15: dest = 0xFF; break;
+ default: dest = 0xFF; break;
+ }
+ }
+
+ if ((src != 0xFF) && (dest != 0xFF))
+ {
+ if (src == Dr)
+ {
+ temp = D;
+ D = Regs[dest];
+ Regs[dest] = temp;
+ }
+ else if (dest == Dr)
+ {
+ temp = D;
+ D = Regs[src];
+ Regs[src] = temp;
+ }
+ else
+ {
+ temp = Regs[src];
+ Regs[src] = Regs[dest];
+ Regs[dest] = temp;
+ }
+ }
+ }
+
+ public void TFR_Func(ushort sel)
+ {
+ ushort src = 0;
+ ushort dest = 0;
+
+ if ((Regs[sel] & 0x8) == 0)
+ {
+ switch (Regs[sel] & 0xF)
+ {
+ case 0: dest = Dr; break;
+ case 1: dest = X; break;
+
+ case 4: dest = SP; break;
+ case 5: dest = PC; break;
+ case 6: dest = 0xFF; break;
+ case 7: dest = 0xFF; break;
+ }
+
+ switch ((Regs[sel] >> 4) & 0xF)
+ {
+ case 0: src = Dr; break;
+ case 1: src = X; break;
+
+ case 4: src = SP; break;
+ case 5: src = PC; break;
+ case 6: src = 0xFF; break;
+ case 7: src = 0xFF; break;
+ default: src = 0xFF; break;
+ }
+ }
+ else
+ {
+ switch (Regs[sel] & 0xF)
+ {
+ case 8: dest = A; break;
+ case 9: dest = B; break;
+ case 10: dest = CC; break;
+ case 11: dest = DP; break;
+ case 12: dest = 0xFF; break;
+ case 13: dest = 0xFF; break;
+ case 14: dest = 0xFF; break;
+ case 15: dest = 0xFF; break;
+ }
+
+ switch ((Regs[sel] >> 4) & 0xF)
+ {
+ case 8: src = A; break;
+ case 9: src = B; break;
+ case 10: src = CC; break;
+ case 11: src = DP; break;
+ case 12: src = 0xFF; break;
+ case 13: src = 0xFF; break;
+ case 14: src = 0xFF; break;
+ case 15: src = 0xFF; break;
+ default: src = 0xFF; break;
+ }
+ }
+
+ if ((src != 0xFF) && (dest != 0xFF))
+ {
+ if (src == Dr)
+ {
+ Regs[dest] = D;
+ }
+ else if (dest == Dr)
+ {
+ D = Regs[src];
+ }
+ else
+ {
+ Regs[dest] = Regs[src];
+ }
+ }
+ }
+ }
+}
diff --git a/BizHawk.Emulation.Cores/CPUs/MC6800/ReadMe.txt b/BizHawk.Emulation.Cores/CPUs/MC6800/ReadMe.txt
new file mode 100644
index 0000000000..115b568cb8
--- /dev/null
+++ b/BizHawk.Emulation.Cores/CPUs/MC6800/ReadMe.txt
@@ -0,0 +1 @@
+TODO: STOP for second byte nonzero
diff --git a/BizHawk.Emulation.Cores/CPUs/MC6800/Registers.cs b/BizHawk.Emulation.Cores/CPUs/MC6800/Registers.cs
new file mode 100644
index 0000000000..9fd091d230
--- /dev/null
+++ b/BizHawk.Emulation.Cores/CPUs/MC6800/Registers.cs
@@ -0,0 +1,87 @@
+using System;
+
+namespace BizHawk.Emulation.Common.Components.MC6800
+{
+ public partial class MC6800
+ {
+ // registers
+ public ushort[] Regs = new ushort[14];
+
+ public const ushort PC = 0;
+ public const ushort SP = 1;
+ public const ushort X = 2;
+ public const ushort A = 3;
+ public const ushort B = 4;
+ public const ushort ADDR = 5; // internal
+ public const ushort ALU = 6; // internal
+ public const ushort ALU2 = 7; // internal
+ public const ushort DP = 8;
+ public const ushort CC = 9;
+ public const ushort Dr = 10;
+ public const ushort IDX_EA = 11;
+
+ public ushort D
+ {
+ get { return (ushort)(Regs[B] | (Regs[A] << 8)); }
+ set { Regs[B] = (ushort)(value & 0xFF); Regs[A] = (ushort)((value >> 8) & 0xFF); }
+ }
+
+ public bool FlagC
+ {
+ get { return (Regs[CC] & 0x01) != 0; }
+ set { Regs[CC] = (byte)((Regs[CC] & ~0x01) | (value ? 0x01 : 0x00)); }
+ }
+
+ public bool FlagV
+ {
+ get { return (Regs[CC] & 0x02) != 0; }
+ set { Regs[CC] = (byte)((Regs[CC] & ~0x02) | (value ? 0x02 : 0x00)); }
+ }
+
+ public bool FlagZ
+ {
+ get { return (Regs[CC] & 0x04) != 0; }
+ set { Regs[CC] = (byte)((Regs[CC] & ~0x04) | (value ? 0x04 : 0x00)); }
+ }
+
+ public bool FlagN
+ {
+ get { return (Regs[CC] & 0x08) != 0; }
+ set { Regs[CC] = (byte)((Regs[CC] & ~0x08) | (value ? 0x08 : 0x00)); }
+ }
+
+ public bool FlagI
+ {
+ get { return (Regs[CC] & 0x10) != 0; }
+ set { Regs[CC] = (byte)((Regs[CC] & ~0x10) | (value ? 0x10 : 0x00)); }
+ }
+
+ public bool FlagH
+ {
+ get { return (Regs[CC] & 0x20) != 0; }
+ set { Regs[CC] = (byte)((Regs[CC] & ~0x20) | (value ? 0x20 : 0x00)); }
+ }
+
+ public bool FlagF
+ {
+ get { return (Regs[CC] & 0x40) != 0; }
+ set { Regs[CC] = (byte)((Regs[CC] & ~0x40) | (value ? 0x40 : 0x00)); }
+ }
+
+ public bool FlagE
+ {
+ get { return (Regs[CC] & 0x80) != 0; }
+ set { Regs[CC] = (byte)((Regs[CC] & ~0x80) | (value ? 0x80 : 0x00)); }
+ }
+
+ private void ResetRegisters()
+ {
+ for (int i = 0; i < 14; i++)
+ {
+ Regs[i] = 0;
+ }
+
+ FlagI = true;
+ }
+ }
+}
\ No newline at end of file