MC6800: Initial commit

This commit is contained in:
alyosha-tas 2019-07-06 20:16:48 -04:00
parent 475702c1e8
commit a4b38aa7a5
10 changed files with 3304 additions and 0 deletions

View File

@ -1543,6 +1543,14 @@
<Compile Include="CPUs\CP1610\CP1610.Disassembler.cs" />
<Compile Include="CPUs\CP1610\CP1610.Execute.cs" />
<Compile Include="CPUs\HuC6280\HuC6280_CDL.cs" />
<Compile Include="CPUs\MC6800\Disassembler.cs" />
<Compile Include="CPUs\MC6800\Execute.cs" />
<Compile Include="CPUs\MC6800\Indexed_Modes.cs" />
<Compile Include="CPUs\MC6800\Interrupts.cs" />
<Compile Include="CPUs\MC6800\MC6800.cs" />
<Compile Include="CPUs\MC6800\Operations.cs" />
<Compile Include="CPUs\MC6800\OP_Tables.cs" />
<Compile Include="CPUs\MC6800\Registers.cs" />
<Compile Include="CPUs\MC6809\Execute.cs" />
<Compile Include="CPUs\MC6809\Interrupts.cs" />
<Compile Include="CPUs\MC6809\MC6809.cs" />

View File

@ -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<ushort, byte> reader, out ushort size)
{
ushort origaddr = addr;
List<byte> bytes = new List<byte>();
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();
}
}
}

View File

@ -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)
}
}
}
}

View File

@ -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;
}
}
}

View File

@ -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;
}
}
}

View File

@ -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<ushort, byte> ReadMemory;
public Action<ushort, byte> WriteMemory;
public Func<ushort, byte> PeekMemory;
public Func<ushort, byte> DummyReadMemory;
// Special Function for Speed switching executed on a STOP
public Func<int, int> SpeedFunc;
//this only calls when the first byte of an instruction is fetched.
public Action<ushort> OnExecFetch;
public void UnregisterMemoryMapper()
{
ReadMemory = null;
ReadMemory = null;
PeekMemory = null;
DummyReadMemory = null;
}
public void SetCallbacks
(
Func<ushort, byte> ReadMemory,
Func<ushort, byte> DummyReadMemory,
Func<ushort, byte> PeekMemory,
Action<ushort, byte> 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<TraceInfo> 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"
)
};
}
/// <summary>
/// Optimization method to set cur_instr
/// </summary>
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();
}
}
}

View File

@ -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;
}
}
}

View File

@ -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];
}
}
}
}
}

View File

@ -0,0 +1 @@
TODO: STOP for second byte nonzero

View File

@ -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;
}
}
}