1222 lines
40 KiB
C#
1222 lines
40 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.Linq;
|
|
|
|
namespace MCEmuCore.GBMonolith
|
|
{
|
|
public struct OpCode
|
|
{
|
|
public readonly byte Instruction;
|
|
public byte? Arg1;
|
|
public byte? Arg2;
|
|
}
|
|
class Cpu
|
|
{
|
|
private readonly CpuRegisters registers;
|
|
#region OpCodes
|
|
|
|
private readonly Dictionary<byte, Func<OpCode, int>> OpCodeTable;
|
|
private readonly Func<OpCode, int>[] OpCodeArray;
|
|
#endregion
|
|
|
|
public Cpu()
|
|
{
|
|
registers = new CpuRegisters();
|
|
|
|
OpCodeTable = new Dictionary<byte, Func<OpCode, int>>()
|
|
{
|
|
#region OpCodes
|
|
#region OpCodes 0x00-0x0F
|
|
{0x00, (op) =>{
|
|
// NOP
|
|
registers.PC += 1;
|
|
return 4;
|
|
} },
|
|
{0x01, (op) =>
|
|
{
|
|
// LD BC,d16
|
|
if (op.Arg1.HasValue && op.Arg2.HasValue)
|
|
{
|
|
ushort operand = (ushort)(op.Arg2 + (op.Arg1 << 8));
|
|
registers.BC = operand;
|
|
registers.PC += 3;
|
|
return 12;
|
|
}
|
|
else
|
|
{
|
|
throw new IllegalInstructionException(op, "Missing arguments for LD BC");
|
|
}
|
|
} },
|
|
{0x02, (op) =>
|
|
{
|
|
// LD (BC), A
|
|
throw new NotImplementedException("LD (BC), A");
|
|
} },
|
|
{0x03, (op) =>
|
|
{
|
|
registers.BC += 1;
|
|
registers.PC += 1;
|
|
return 8;
|
|
} },
|
|
{0x04, (op) =>
|
|
{
|
|
// INC B
|
|
byte reg = (byte)(registers.B + 1);
|
|
registers.B = reg;
|
|
|
|
registers.Flags.Subtract = false;
|
|
registers.Flags.Zero = reg == 0;
|
|
// This logic only works for the increment operation
|
|
registers.Flags.HalfCarry = reg == 16;
|
|
|
|
registers.PC += 1;
|
|
return 4;
|
|
} },
|
|
{0x05, (op) =>
|
|
{
|
|
// DEC B
|
|
byte reg = (byte)((uint)registers.B - 1);
|
|
registers.B = reg;
|
|
|
|
registers.Flags.Subtract = true;
|
|
registers.Flags.Zero = reg == 0;
|
|
// This logic only works for the decrement operation
|
|
registers.Flags.HalfCarry = reg == 15;
|
|
|
|
registers.PC += 1;
|
|
return 4;
|
|
} },
|
|
{0x06, (op) =>
|
|
{
|
|
// LD B,d8
|
|
if (op.Arg1.HasValue)
|
|
{
|
|
registers.B = op.Arg1.Value;
|
|
registers.PC += 2;
|
|
return 8;
|
|
}
|
|
else
|
|
{
|
|
throw new IllegalInstructionException(op, "Missing arguments for LD B");
|
|
}
|
|
} },
|
|
{0x07, (op) =>
|
|
{
|
|
// RLCA
|
|
registers.Flags.Zero = false;
|
|
registers.Flags.Subtract = false;
|
|
registers.Flags.HalfCarry = false;
|
|
registers.Flags.Carry = (registers.A & 0b1000_0000) != 0;
|
|
|
|
registers.A = (byte)((registers.A << 1) + (registers.A >> 7));
|
|
registers.PC += 1;
|
|
return 4;
|
|
} },
|
|
{0x08, (op) =>
|
|
{
|
|
// LD (a16), SP
|
|
// Load SP into address
|
|
throw new NotImplementedException("LD (a16), SP");
|
|
} },
|
|
{0x09, (op) =>
|
|
{
|
|
// ADD HL, BC
|
|
registers.Flags.Subtract = false;
|
|
registers.Flags.HalfCarry = (((registers.HL & 0x0FFF) + (registers.BC & 0x0FFF) & 0x1000) == 0x1000);
|
|
registers.Flags.Carry = (((registers.HL + registers.BC) & 0x10000) == 0x10000);
|
|
|
|
registers.HL += registers.BC;
|
|
registers.PC += 1;
|
|
|
|
return 8;
|
|
} },
|
|
{0x0A, (op) =>
|
|
{
|
|
// LD A, (BC)
|
|
// Load byte at address stored in BC into A
|
|
throw new NotImplementedException("LD A, (BC)");
|
|
} },
|
|
{0x0B, (op) =>
|
|
{
|
|
// DEC BC
|
|
registers.BC -= 1;
|
|
registers.PC += 1;
|
|
return 8;
|
|
} },
|
|
{0x0C, (op) =>
|
|
{
|
|
// INC C
|
|
byte reg = (byte)(registers.C + 1);
|
|
registers.C = reg;
|
|
|
|
registers.Flags.Subtract = false;
|
|
registers.Flags.Zero = reg == 0;
|
|
// This logic only works for the increment operation
|
|
registers.Flags.HalfCarry = reg == 16;
|
|
|
|
registers.PC += 1;
|
|
return 4;
|
|
} },
|
|
{0x0D, (op) =>
|
|
{
|
|
// DEC C
|
|
byte reg = (byte)((uint)registers.C - 1);
|
|
registers.C = reg;
|
|
|
|
registers.Flags.Subtract = true;
|
|
registers.Flags.Zero = reg == 0;
|
|
// This logic only works for the decrement operation
|
|
registers.Flags.HalfCarry = reg == 15;
|
|
|
|
registers.PC += 1;
|
|
return 4;
|
|
} },
|
|
{0x0E, (op) =>
|
|
{
|
|
// LD C,d8
|
|
if (op.Arg1.HasValue)
|
|
{
|
|
registers.C = op.Arg1.Value;
|
|
registers.PC += 2;
|
|
return 8;
|
|
}
|
|
else
|
|
{
|
|
throw new IllegalInstructionException(op, "Missing argument for LD B");
|
|
}
|
|
} },
|
|
{0x0F, (op) =>
|
|
{
|
|
// RRCA
|
|
registers.Flags.Zero = false;
|
|
registers.Flags.Subtract = false;
|
|
registers.Flags.HalfCarry = false;
|
|
registers.Flags.Carry = (registers.A & 0b0000_0001) != 0;
|
|
|
|
registers.A = (byte)((registers.A >> 1) + (registers.A << 7));
|
|
registers.PC += 1;
|
|
return 4;
|
|
} },
|
|
#endregion
|
|
#region OpCodes 0x10-0x1F
|
|
{0x10, (op) =>
|
|
{
|
|
// STOP 0
|
|
// Halts CPU & LCD until button pressed
|
|
throw new NotImplementedException("STOP");
|
|
} },
|
|
{0x11, (op) =>
|
|
{
|
|
// LD DE, d16
|
|
throw new NotImplementedException("0x11");
|
|
} },
|
|
{0x12, (op) =>
|
|
{
|
|
// LD (DE), A
|
|
throw new NotImplementedException("0x12");
|
|
} },
|
|
{0x13, (op) =>
|
|
{
|
|
// INC DE
|
|
throw new NotImplementedException("0x13");
|
|
} },
|
|
{0x14, (op) =>
|
|
{
|
|
throw new NotImplementedException("0x14");
|
|
} },
|
|
{0x15, (op) =>
|
|
{
|
|
throw new NotImplementedException("0x15");
|
|
} },
|
|
{0x16, (op) =>
|
|
{
|
|
throw new NotImplementedException("0x16");
|
|
} },
|
|
{0x17, (op) =>
|
|
{
|
|
throw new NotImplementedException("0x17");
|
|
} },
|
|
{0x18, (op) =>
|
|
{
|
|
throw new NotImplementedException("0x18");
|
|
} },
|
|
{0x19, (op) =>
|
|
{
|
|
throw new NotImplementedException("0x19");
|
|
} },
|
|
{0x1A, (op) =>
|
|
{
|
|
throw new NotImplementedException("0x1A");
|
|
} },
|
|
{0x1B, (op) =>
|
|
{
|
|
throw new NotImplementedException("0x1B");
|
|
} },
|
|
{0x1C, (op) =>
|
|
{
|
|
throw new NotImplementedException("0c1C");
|
|
} },
|
|
{0x1D, (op) =>
|
|
{
|
|
throw new NotImplementedException("0x1D");
|
|
} },
|
|
{0x1E, (op) =>
|
|
{
|
|
throw new NotImplementedException("0x1E");
|
|
} },
|
|
{0x1F, (op) =>
|
|
{
|
|
throw new NotImplementedException("0x1F");
|
|
} },
|
|
#endregion
|
|
#region OpCodes 0x20-0x2F
|
|
{0x20, (op) =>
|
|
{
|
|
throw new NotImplementedException("0x20");
|
|
} },
|
|
{0x21, (op) =>
|
|
{
|
|
throw new NotImplementedException("0x21");
|
|
} },
|
|
{0x22, (op) =>
|
|
{
|
|
throw new NotImplementedException("0x22");
|
|
} },
|
|
{0x23, (op) =>
|
|
{
|
|
throw new NotImplementedException("0x23");
|
|
} },
|
|
{0x24, (op) =>
|
|
{
|
|
throw new NotImplementedException("0x24");
|
|
} },
|
|
{0x25, (op) =>
|
|
{
|
|
throw new NotImplementedException("0x25");
|
|
} },
|
|
{0x26, (op) =>
|
|
{
|
|
throw new NotImplementedException("0x26");
|
|
} },
|
|
{0x27, (op) =>
|
|
{
|
|
throw new NotImplementedException("0x27");
|
|
} },
|
|
{0x28, (op) =>
|
|
{
|
|
throw new NotImplementedException("0x28");
|
|
} },
|
|
{0x29, (op) =>
|
|
{
|
|
throw new NotImplementedException("0x29");
|
|
} },
|
|
{0x2A, (op) =>
|
|
{
|
|
throw new NotImplementedException("0x2A");
|
|
} },
|
|
{0x2B, (op) =>
|
|
{
|
|
throw new NotImplementedException("0x2B");
|
|
} },
|
|
{0x2C, (op) =>
|
|
{
|
|
throw new NotImplementedException("0x2C");
|
|
} },
|
|
{0x2D, (op) =>
|
|
{
|
|
throw new NotImplementedException("0x2D");
|
|
} },
|
|
{0x2E, (op) =>
|
|
{
|
|
throw new NotImplementedException("0x2E");
|
|
} },
|
|
{0x2F, (op) =>
|
|
{
|
|
throw new NotImplementedException("0x2F");
|
|
} },
|
|
#endregion
|
|
#region OpCodes 0x30-0x3F
|
|
{0x30, (op) =>
|
|
{
|
|
throw new NotImplementedException("0x30");
|
|
} },
|
|
{0x31, (op) =>
|
|
{
|
|
throw new NotImplementedException("0x31");
|
|
} },
|
|
{0x32, (op) =>
|
|
{
|
|
throw new NotImplementedException("0x32");
|
|
} },
|
|
{0x33, (op) =>
|
|
{
|
|
throw new NotImplementedException("0x33");
|
|
} },
|
|
{0x34, (op) =>
|
|
{
|
|
throw new NotImplementedException("0x34");
|
|
} },
|
|
{0x35, (op) =>
|
|
{
|
|
throw new NotImplementedException("0x35");
|
|
} },
|
|
{0x36, (op) =>
|
|
{
|
|
throw new NotImplementedException("0x36");
|
|
} },
|
|
{0x37, (op) =>
|
|
{
|
|
throw new NotImplementedException("0x37");
|
|
} },
|
|
{0x38, (op) =>
|
|
{
|
|
throw new NotImplementedException("0x38");
|
|
} },
|
|
{0x39, (op) =>
|
|
{
|
|
throw new NotImplementedException("0x39");
|
|
} },
|
|
{0x3A, (op) =>
|
|
{
|
|
throw new NotImplementedException("0x3A");
|
|
} },
|
|
{0x3B, (op) =>
|
|
{
|
|
throw new NotImplementedException("0x3B");
|
|
} },
|
|
{0x3C, (op) =>
|
|
{
|
|
throw new NotImplementedException("0x3C");
|
|
} },
|
|
{0x3D, (op) =>
|
|
{
|
|
throw new NotImplementedException("0x3D");
|
|
} },
|
|
{0x3E, (op) =>
|
|
{
|
|
throw new NotImplementedException("0x3E");
|
|
} },
|
|
{0x3F, (op) =>
|
|
{
|
|
throw new NotImplementedException("0x3F");
|
|
} },
|
|
#endregion
|
|
#region OpCodes 0x40-0x4F
|
|
{0x40, (op) =>
|
|
{
|
|
throw new NotImplementedException("0x40");
|
|
} },
|
|
{0x41, (op) =>
|
|
{
|
|
throw new NotImplementedException("0x41");
|
|
} },
|
|
{0x42, (op) =>
|
|
{
|
|
throw new NotImplementedException("0x42");
|
|
} },
|
|
{0x43, (op) =>
|
|
{
|
|
throw new NotImplementedException("0x43");
|
|
} },
|
|
{0x44, (op) =>
|
|
{
|
|
throw new NotImplementedException("0x44");
|
|
} },
|
|
{0x45, (op) =>
|
|
{
|
|
throw new NotImplementedException("0x45");
|
|
} },
|
|
{0x46, (op) =>
|
|
{
|
|
throw new NotImplementedException("0x46");
|
|
} },
|
|
{0x47, (op) =>
|
|
{
|
|
throw new NotImplementedException("0x47");
|
|
} },
|
|
{0x48, (op) =>
|
|
{
|
|
throw new NotImplementedException("0x48");
|
|
} },
|
|
{0x49, (op) =>
|
|
{
|
|
throw new NotImplementedException("0x49");
|
|
} },
|
|
{0x4A, (op) =>
|
|
{
|
|
throw new NotImplementedException("0x4A");
|
|
} },
|
|
{0x4B, (op) =>
|
|
{
|
|
throw new NotImplementedException("0x4B");
|
|
} },
|
|
{0x4C, (op) =>
|
|
{
|
|
throw new NotImplementedException("0x4C");
|
|
} },
|
|
{0x4D, (op) =>
|
|
{
|
|
throw new NotImplementedException("0x4D");
|
|
} },
|
|
{0x4E, (op) =>
|
|
{
|
|
throw new NotImplementedException("0x4E");
|
|
} },
|
|
{0x4F, (op) =>
|
|
{
|
|
throw new NotImplementedException("0x4F");
|
|
} },
|
|
#endregion
|
|
#region OpCodes 0x50-0x5F
|
|
{0x50, (op) =>
|
|
{
|
|
throw new NotImplementedException("0x50");
|
|
} },
|
|
{0x51, (op) =>
|
|
{
|
|
throw new NotImplementedException("0x51");
|
|
} },
|
|
{0x52, (op) =>
|
|
{
|
|
throw new NotImplementedException("0x52");
|
|
} },
|
|
{0x53, (op) =>
|
|
{
|
|
throw new NotImplementedException("0x53");
|
|
} },
|
|
{0x54, (op) =>
|
|
{
|
|
throw new NotImplementedException("0x54");
|
|
} },
|
|
{0x55, (op) =>
|
|
{
|
|
throw new NotImplementedException("0x55");
|
|
} },
|
|
{0x56, (op) =>
|
|
{
|
|
throw new NotImplementedException("0x56");
|
|
} },
|
|
{0x57, (op) =>
|
|
{
|
|
throw new NotImplementedException("0x57");
|
|
} },
|
|
{0x58, (op) =>
|
|
{
|
|
throw new NotImplementedException("0x58");
|
|
} },
|
|
{0x59, (op) =>
|
|
{
|
|
throw new NotImplementedException("0x59");
|
|
} },
|
|
{0x5A, (op) =>
|
|
{
|
|
throw new NotImplementedException("0x5A");
|
|
} },
|
|
{0x5B, (op) =>
|
|
{
|
|
throw new NotImplementedException("0x5B");
|
|
} },
|
|
{0x5C, (op) =>
|
|
{
|
|
throw new NotImplementedException("0x5C");
|
|
} },
|
|
{0x5D, (op) =>
|
|
{
|
|
throw new NotImplementedException("0x5D");
|
|
} },
|
|
{0x5E, (op) =>
|
|
{
|
|
throw new NotImplementedException("0x5E");
|
|
} },
|
|
{0x5F, (op) =>
|
|
{
|
|
throw new NotImplementedException("0x5F");
|
|
} },
|
|
#endregion
|
|
#region OpCodes 0x60-0x6F
|
|
{0x60, (op) =>
|
|
{
|
|
throw new NotImplementedException("0x60");
|
|
} },
|
|
{0x61, (op) =>
|
|
{
|
|
throw new NotImplementedException("0x61");
|
|
} },
|
|
{0x62, (op) =>
|
|
{
|
|
throw new NotImplementedException("0x62");
|
|
} },
|
|
{0x63, (op) =>
|
|
{
|
|
throw new NotImplementedException("0x63");
|
|
} },
|
|
{0x64, (op) =>
|
|
{
|
|
throw new NotImplementedException("0x64");
|
|
} },
|
|
{0x65, (op) =>
|
|
{
|
|
throw new NotImplementedException("0x65");
|
|
} },
|
|
{0x66, (op) =>
|
|
{
|
|
throw new NotImplementedException("0x66");
|
|
} },
|
|
{0x67, (op) =>
|
|
{
|
|
throw new NotImplementedException("0x67");
|
|
} },
|
|
{0x68, (op) =>
|
|
{
|
|
throw new NotImplementedException("0x68");
|
|
} },
|
|
{0x69, (op) =>
|
|
{
|
|
throw new NotImplementedException("0x69");
|
|
} },
|
|
{0x6A, (op) =>
|
|
{
|
|
throw new NotImplementedException("0x6A");
|
|
} },
|
|
{0x6B, (op) =>
|
|
{
|
|
throw new NotImplementedException("0x6B");
|
|
} },
|
|
{0x6C, (op) =>
|
|
{
|
|
throw new NotImplementedException("0x6C");
|
|
} },
|
|
{0x6D, (op) =>
|
|
{
|
|
throw new NotImplementedException("0x6D");
|
|
} },
|
|
{0x6E, (op) =>
|
|
{
|
|
throw new NotImplementedException("0x6E");
|
|
} },
|
|
{0x6F, (op) =>
|
|
{
|
|
throw new NotImplementedException("0x6F");
|
|
} },
|
|
#endregion
|
|
#region OpCodes 0x70-0x7F
|
|
{0x70, (op) =>
|
|
{
|
|
throw new NotImplementedException("0x70");
|
|
} },
|
|
{0x71, (op) =>
|
|
{
|
|
throw new NotImplementedException("0x71");
|
|
} },
|
|
{0x72, (op) =>
|
|
{
|
|
throw new NotImplementedException("0x72");
|
|
} },
|
|
{0x73, (op) =>
|
|
{
|
|
throw new NotImplementedException("0x73");
|
|
} },
|
|
{0x74, (op) =>
|
|
{
|
|
throw new NotImplementedException("0x74");
|
|
} },
|
|
{0x75, (op) =>
|
|
{
|
|
throw new NotImplementedException("0x75");
|
|
} },
|
|
{0x76, (op) =>
|
|
{
|
|
throw new NotImplementedException("0x76");
|
|
} },
|
|
{0x77, (op) =>
|
|
{
|
|
throw new NotImplementedException("0x77");
|
|
} },
|
|
{0x78, (op) =>
|
|
{
|
|
throw new NotImplementedException("0x78");
|
|
} },
|
|
{0x79, (op) =>
|
|
{
|
|
throw new NotImplementedException("0x79");
|
|
} },
|
|
{0x7A, (op) =>
|
|
{
|
|
throw new NotImplementedException("0x7A");
|
|
} },
|
|
{0x7B, (op) =>
|
|
{
|
|
throw new NotImplementedException("0x7B");
|
|
} },
|
|
{0x7C, (op) =>
|
|
{
|
|
throw new NotImplementedException("0x7C");
|
|
} },
|
|
{0x7D, (op) =>
|
|
{
|
|
throw new NotImplementedException("0x7D");
|
|
} },
|
|
{0x7E, (op) =>
|
|
{
|
|
throw new NotImplementedException("0x7E");
|
|
} },
|
|
{0x7F, (op) =>
|
|
{
|
|
throw new NotImplementedException("0x7F");
|
|
} },
|
|
#endregion
|
|
#region OpCodes 0x80-0x8F
|
|
{0x80, (op) =>
|
|
{
|
|
throw new NotImplementedException("0x80");
|
|
} },
|
|
{0x81, (op) =>
|
|
{
|
|
throw new NotImplementedException("0x81");
|
|
} },
|
|
{0x82, (op) =>
|
|
{
|
|
throw new NotImplementedException("0x82");
|
|
} },
|
|
{0x83, (op) =>
|
|
{
|
|
throw new NotImplementedException("0x83");
|
|
} },
|
|
{0x84, (op) =>
|
|
{
|
|
throw new NotImplementedException("0x84");
|
|
} },
|
|
{0x85, (op) =>
|
|
{
|
|
throw new NotImplementedException("0x85");
|
|
} },
|
|
{0x86, (op) =>
|
|
{
|
|
throw new NotImplementedException("0x86");
|
|
} },
|
|
{0x87, (op) =>
|
|
{
|
|
throw new NotImplementedException("0x87");
|
|
} },
|
|
{0x88, (op) =>
|
|
{
|
|
throw new NotImplementedException("0x88");
|
|
} },
|
|
{0x89, (op) =>
|
|
{
|
|
throw new NotImplementedException("0x89");
|
|
} },
|
|
{0x8A, (op) =>
|
|
{
|
|
throw new NotImplementedException("0x8A");
|
|
} },
|
|
{0x8B, (op) =>
|
|
{
|
|
throw new NotImplementedException("0x8B");
|
|
} },
|
|
{0x8C, (op) =>
|
|
{
|
|
throw new NotImplementedException("0x8C");
|
|
} },
|
|
{0x8D, (op) =>
|
|
{
|
|
throw new NotImplementedException("0x8D");
|
|
} },
|
|
{0x8E, (op) =>
|
|
{
|
|
throw new NotImplementedException("0x8E");
|
|
} },
|
|
{0x8F, (op) =>
|
|
{
|
|
throw new NotImplementedException("0x8F");
|
|
} },
|
|
#endregion
|
|
#region OpCodes 0x90-0x9F
|
|
{0x90, (op) =>
|
|
{
|
|
throw new NotImplementedException("0x90");
|
|
} },
|
|
{0x91, (op) =>
|
|
{
|
|
throw new NotImplementedException("0x91");
|
|
} },
|
|
{0x92, (op) =>
|
|
{
|
|
throw new NotImplementedException("0x92");
|
|
} },
|
|
{0x93, (op) =>
|
|
{
|
|
throw new NotImplementedException("0x93");
|
|
} },
|
|
{0x94, (op) =>
|
|
{
|
|
throw new NotImplementedException("0x94");
|
|
} },
|
|
{0x95, (op) =>
|
|
{
|
|
throw new NotImplementedException("0x95");
|
|
} },
|
|
{0x96, (op) =>
|
|
{
|
|
throw new NotImplementedException("0x96");
|
|
} },
|
|
{0x97, (op) =>
|
|
{
|
|
throw new NotImplementedException("0x97");
|
|
} },
|
|
{0x98, (op) =>
|
|
{
|
|
throw new NotImplementedException("0x98");
|
|
} },
|
|
{0x99, (op) =>
|
|
{
|
|
throw new NotImplementedException("0x99");
|
|
} },
|
|
{0x9A, (op) =>
|
|
{
|
|
throw new NotImplementedException("0x9A");
|
|
} },
|
|
{0x9B, (op) =>
|
|
{
|
|
throw new NotImplementedException("0x9B");
|
|
} },
|
|
{0x9C, (op) =>
|
|
{
|
|
throw new NotImplementedException("0x9C");
|
|
} },
|
|
{0x9D, (op) =>
|
|
{
|
|
throw new NotImplementedException("0x9D");
|
|
} },
|
|
{0x9E, (op) =>
|
|
{
|
|
throw new NotImplementedException("0x9E");
|
|
} },
|
|
{0x9F, (op) =>
|
|
{
|
|
throw new NotImplementedException("0x9F");
|
|
} },
|
|
#endregion
|
|
#region OpCodes 0xA0-0xAF
|
|
{0xA0, (op) =>
|
|
{
|
|
throw new NotImplementedException("0xA0");
|
|
} },
|
|
{0xA1, (op) =>
|
|
{
|
|
throw new NotImplementedException("0xA1");
|
|
} },
|
|
{0xA2, (op) =>
|
|
{
|
|
throw new NotImplementedException("0xA2");
|
|
} },
|
|
{0xA3, (op) =>
|
|
{
|
|
throw new NotImplementedException("0xA3");
|
|
} },
|
|
{0xA4, (op) =>
|
|
{
|
|
throw new NotImplementedException("0xA4");
|
|
} },
|
|
{0xA5, (op) =>
|
|
{
|
|
throw new NotImplementedException("0xA5");
|
|
} },
|
|
{0xA6, (op) =>
|
|
{
|
|
throw new NotImplementedException("0xA6");
|
|
} },
|
|
{0xA7, (op) =>
|
|
{
|
|
throw new NotImplementedException("0xA7");
|
|
} },
|
|
{0xA8, (op) =>
|
|
{
|
|
throw new NotImplementedException("0xA8");
|
|
} },
|
|
{0xA9, (op) =>
|
|
{
|
|
throw new NotImplementedException("0xA9");
|
|
} },
|
|
{0xAA, (op) =>
|
|
{
|
|
throw new NotImplementedException("0xAA");
|
|
} },
|
|
{0xAB, (op) =>
|
|
{
|
|
throw new NotImplementedException("0xAB");
|
|
} },
|
|
{0xAC, (op) =>
|
|
{
|
|
throw new NotImplementedException("0xAC");
|
|
} },
|
|
{0xAD, (op) =>
|
|
{
|
|
throw new NotImplementedException("0xAD");
|
|
} },
|
|
{0xAE, (op) =>
|
|
{
|
|
throw new NotImplementedException("0xAE");
|
|
} },
|
|
{0xAF, (op) =>
|
|
{
|
|
throw new NotImplementedException("0xAF");
|
|
} },
|
|
#endregion
|
|
#region OpCodes 0xB0-0xBF
|
|
{0xB0, (op) =>
|
|
{
|
|
throw new NotImplementedException("0xB0");
|
|
} },
|
|
{0xB1, (op) =>
|
|
{
|
|
throw new NotImplementedException("0xB1");
|
|
} },
|
|
{0xB2, (op) =>
|
|
{
|
|
throw new NotImplementedException("0xB2");
|
|
} },
|
|
{0xB3, (op) =>
|
|
{
|
|
throw new NotImplementedException("0xB3");
|
|
} },
|
|
{0xB4, (op) =>
|
|
{
|
|
throw new NotImplementedException("0xB4");
|
|
} },
|
|
{0xB5, (op) =>
|
|
{
|
|
throw new NotImplementedException("0xB5");
|
|
} },
|
|
{0xB6, (op) =>
|
|
{
|
|
throw new NotImplementedException("0xB6");
|
|
} },
|
|
{0xB7, (op) =>
|
|
{
|
|
throw new NotImplementedException("0xB7");
|
|
} },
|
|
{0xB8, (op) =>
|
|
{
|
|
throw new NotImplementedException("0xB8");
|
|
} },
|
|
{0xB9, (op) =>
|
|
{
|
|
throw new NotImplementedException("0xB9");
|
|
} },
|
|
{0xBA, (op) =>
|
|
{
|
|
throw new NotImplementedException("0xBA");
|
|
} },
|
|
{0xBB, (op) =>
|
|
{
|
|
throw new NotImplementedException("0xBB");
|
|
} },
|
|
{0xBC, (op) =>
|
|
{
|
|
throw new NotImplementedException("0xBC");
|
|
} },
|
|
{0xBD, (op) =>
|
|
{
|
|
throw new NotImplementedException("0xBD");
|
|
} },
|
|
{0xBE, (op) =>
|
|
{
|
|
throw new NotImplementedException("0xBE");
|
|
} },
|
|
{0xBF, (op) =>
|
|
{
|
|
throw new NotImplementedException("0xBF");
|
|
} },
|
|
#endregion
|
|
#region OpCodes 0xC0-0xCF
|
|
{0xC0, (op) =>
|
|
{
|
|
throw new NotImplementedException("0xC0");
|
|
} },
|
|
{0xC1, (op) =>
|
|
{
|
|
throw new NotImplementedException("0xC1");
|
|
} },
|
|
{0xC2, (op) =>
|
|
{
|
|
throw new NotImplementedException("0xC2");
|
|
} },
|
|
{0xC3, (op) =>
|
|
{
|
|
throw new NotImplementedException("0xC3");
|
|
} },
|
|
{0xC4, (op) =>
|
|
{
|
|
throw new NotImplementedException("0xC4");
|
|
} },
|
|
{0xC5, (op) =>
|
|
{
|
|
throw new NotImplementedException("0xC5");
|
|
} },
|
|
{0xC6, (op) =>
|
|
{
|
|
throw new NotImplementedException("0xC6");
|
|
} },
|
|
{0xC7, (op) =>
|
|
{
|
|
throw new NotImplementedException("0xC7");
|
|
} },
|
|
{0xC8, (op) =>
|
|
{
|
|
throw new NotImplementedException("0xC8");
|
|
} },
|
|
{0xC9, (op) =>
|
|
{
|
|
throw new NotImplementedException("0xC9");
|
|
} },
|
|
{0xCA, (op) =>
|
|
{
|
|
throw new NotImplementedException("0xCA");
|
|
} },
|
|
{0xCB, (op) =>
|
|
{
|
|
throw new NotImplementedException("0xCB");
|
|
} },
|
|
{0xCC, (op) =>
|
|
{
|
|
throw new NotImplementedException("0xCC");
|
|
} },
|
|
{0xCD, (op) =>
|
|
{
|
|
throw new NotImplementedException("0xCD");
|
|
} },
|
|
{0xCE, (op) =>
|
|
{
|
|
throw new NotImplementedException("0xCE");
|
|
} },
|
|
{0xCF, (op) =>
|
|
{
|
|
throw new NotImplementedException("0xCF");
|
|
} },
|
|
#endregion
|
|
#region OpCodes 0xD0-0xDF
|
|
{0xD0, (op) =>
|
|
{
|
|
throw new NotImplementedException("0xD0");
|
|
} },
|
|
{0xD1, (op) =>
|
|
{
|
|
throw new NotImplementedException("0xD1");
|
|
} },
|
|
{0xD2, (op) =>
|
|
{
|
|
throw new NotImplementedException("0xD2");
|
|
} },
|
|
{0xD3, (op) =>
|
|
{
|
|
throw new IllegalInstructionException(op, "Instruction does not exist");
|
|
} },
|
|
{0xD4, (op) =>
|
|
{
|
|
throw new NotImplementedException("0xD4");
|
|
} },
|
|
{0xD5, (op) =>
|
|
{
|
|
throw new NotImplementedException("0xD5");
|
|
} },
|
|
{0xD6, (op) =>
|
|
{
|
|
throw new NotImplementedException("0xD6");
|
|
} },
|
|
{0xD7, (op) =>
|
|
{
|
|
throw new NotImplementedException("0xD7");
|
|
} },
|
|
{0xD8, (op) =>
|
|
{
|
|
throw new NotImplementedException("0xD8");
|
|
} },
|
|
{0xD9, (op) =>
|
|
{
|
|
throw new NotImplementedException("0xD9");
|
|
} },
|
|
{0xDA, (op) =>
|
|
{
|
|
throw new NotImplementedException("0xDA");
|
|
} },
|
|
{0xDB, (op) =>
|
|
{
|
|
throw new IllegalInstructionException(op, "Instruction does not exist");
|
|
} },
|
|
{0xDC, (op) =>
|
|
{
|
|
throw new NotImplementedException("0xDC");
|
|
} },
|
|
{0xDD, (op) =>
|
|
{
|
|
throw new IllegalInstructionException(op, "Instruction does not exist");
|
|
} },
|
|
{0xDE, (op) =>
|
|
{
|
|
throw new NotImplementedException("0xDE");
|
|
} },
|
|
{0xDF, (op) =>
|
|
{
|
|
throw new NotImplementedException("0xDF");
|
|
} },
|
|
#endregion
|
|
#region OpCodes 0xE0-0xEF
|
|
{0xE0, (op) =>
|
|
{
|
|
throw new NotImplementedException("0xE0");
|
|
} },
|
|
{0xE1, (op) =>
|
|
{
|
|
throw new NotImplementedException("0xE1");
|
|
} },
|
|
{0xE2, (op) =>
|
|
{
|
|
throw new NotImplementedException("0xE2");
|
|
} },
|
|
{0xE3, (op) =>
|
|
{
|
|
throw new IllegalInstructionException(op, "Instruction does not exist");
|
|
} },
|
|
{0xE4, (op) =>
|
|
{
|
|
throw new IllegalInstructionException(op, "Instruction does not exist");
|
|
} },
|
|
{0xE5, (op) =>
|
|
{
|
|
throw new NotImplementedException("0xE5");
|
|
} },
|
|
{0xE6, (op) =>
|
|
{
|
|
throw new NotImplementedException("0xE6");
|
|
} },
|
|
{0xE7, (op) =>
|
|
{
|
|
throw new NotImplementedException("0xE7");
|
|
} },
|
|
{0xE8, (op) =>
|
|
{
|
|
throw new NotImplementedException("0xE8");
|
|
} },
|
|
{0xE9, (op) =>
|
|
{
|
|
throw new NotImplementedException("0xE9");
|
|
} },
|
|
{0xEA, (op) =>
|
|
{
|
|
throw new NotImplementedException("0xEA");
|
|
} },
|
|
{0xEB, (op) =>
|
|
{
|
|
throw new IllegalInstructionException(op, "Instruction does not exist");
|
|
} },
|
|
{0xEC, (op) =>
|
|
{
|
|
throw new IllegalInstructionException(op, "Instruction does not exist");
|
|
} },
|
|
{0xED, (op) =>
|
|
{
|
|
throw new IllegalInstructionException(op, "Instruction does not exist");
|
|
} },
|
|
{0xEE, (op) =>
|
|
{
|
|
throw new NotImplementedException("0xEE");
|
|
} },
|
|
{0xEF, (op) =>
|
|
{
|
|
throw new NotImplementedException("0xEF");
|
|
} },
|
|
#endregion
|
|
#region OpCodes 0xF0-0xFF
|
|
{0xF0, (op) =>
|
|
{
|
|
throw new NotImplementedException("0xF0");
|
|
} },
|
|
{0xF1, (op) =>
|
|
{
|
|
throw new NotImplementedException("0xF1");
|
|
} },
|
|
{0xF2, (op) =>
|
|
{
|
|
throw new NotImplementedException("0xF2");
|
|
} },
|
|
{0xF3, (op) =>
|
|
{
|
|
throw new NotImplementedException("0xF3");
|
|
} },
|
|
{0xF4, (op) =>
|
|
{
|
|
throw new IllegalInstructionException(op, "Instruction does not exist");
|
|
} },
|
|
{0xF5, (op) =>
|
|
{
|
|
throw new NotImplementedException("0xF5");
|
|
} },
|
|
{0xF6, (op) =>
|
|
{
|
|
throw new NotImplementedException("0xF6");
|
|
} },
|
|
{0xF7, (op) =>
|
|
{
|
|
throw new NotImplementedException("0xF7");
|
|
} },
|
|
{0xF8, (op) =>
|
|
{
|
|
throw new NotImplementedException("0xF8");
|
|
} },
|
|
{0xF9, (op) =>
|
|
{
|
|
throw new NotImplementedException("0xF9");
|
|
} },
|
|
{0xFA, (op) =>
|
|
{
|
|
throw new NotImplementedException("0xFA");
|
|
} },
|
|
{0xFB, (op) =>
|
|
{
|
|
throw new NotImplementedException("0xFB");
|
|
} },
|
|
{0xFC, (op) =>
|
|
{
|
|
throw new IllegalInstructionException(op, "Instruction does not exist");
|
|
} },
|
|
{0xFD, (op) =>
|
|
{
|
|
throw new IllegalInstructionException(op, "Instruction does not exist");
|
|
} },
|
|
{0xFE, (op) =>
|
|
{
|
|
throw new NotImplementedException("0xFE");
|
|
} },
|
|
{0xFF, (op) =>
|
|
{
|
|
throw new NotImplementedException("0xFF");
|
|
} },
|
|
#endregion
|
|
#endregion
|
|
};
|
|
|
|
// Arrays are faster than dictionaries?
|
|
// TODO: Test speed of dictionary vs array
|
|
OpCodeArray = OpCodeTable.OrderBy(o => o.Key).Select(o => o.Value).ToArray();
|
|
}
|
|
}
|
|
|
|
|
|
[Serializable]
|
|
public class IllegalInstructionException : Exception
|
|
{
|
|
public OpCode OpCode { get; set; }
|
|
public IllegalInstructionException() { }
|
|
public IllegalInstructionException(OpCode opCode, string message) : base(message)
|
|
{
|
|
OpCode = opCode;
|
|
}
|
|
public IllegalInstructionException(string message) : base(message) { }
|
|
public IllegalInstructionException(string message, Exception inner) : base(message, inner) { }
|
|
protected IllegalInstructionException(
|
|
System.Runtime.Serialization.SerializationInfo info,
|
|
System.Runtime.Serialization.StreamingContext context) : base(info, context) { }
|
|
}
|
|
}
|