Files
MCEmuCore/MCEmuCore.GBMonolith/Cpu.cs
2020-05-15 21:03:35 -06:00

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