Ejemplo n.º 1
0
        /// <summary>
        /// Constructor.
        /// </summary>
        public Processor()
        {
            // Initialize the RAM with 64K
            ram = new Memory(256 * 256);

            // Initialize the internal Registers
            instruction    = new InstructionRegister();
            programCounter = new Register16();

            // Initialize the ALU Registers
            a = new Register();
            b = new Register();
            c = new Register();

            // Initialize the 8-bit General Purpose Registers
            d  = new Register();
            e  = new Register();
            f  = new Register();
            g  = new Register();
            h  = new Register();
            xl = new Register();
            xh = new Register();

            // Initialize the 16-bit General Purpose Registers
            m  = new Register16();
            j  = new Register16();
            sp = new Register16();
            bp = new Register16();
            y  = new Register16();
            z  = new Register16();

            // Initialize the Flags Register
            flags      = new Register();
            flagsSaved = new Register();

            // Initialize the breakpoint Array
            breakpointAddresses = new List <string>();

            // Initialize the individual Carry Flags
            carryADD = false;
            carrySUB = false;
            carrySHL = false;
            carrySHR = false;
        }
Ejemplo n.º 2
0
        /// <summary>
        /// Executes the next Instruction and increments the Program Counter.
        /// </summary>
        private CPUExecution ExecuteNextInstruction(out string OutputPortC, out string OutputPortD)
        {
            bool incrementProgramCounter = true;

            OutputPortC = string.Empty;
            OutputPortD = string.Empty;

            // Check if we are at a breakpoint
            if (!breakpointAddresses.Contains(programCounter.GetString()))
            {
                // Fetch the current instruction from the RAM
                instruction.SetBits(ram.ReadValue(programCounter.GetInt()));

                switch (instruction.GetOpCode())
                {
                case OpCode.HLT:
                {
                    // We have finished the end of the program execution
                    return(CPUExecution.FINISHED);
                }

                case OpCode.INT:
                {
                    // We have to raise an software based interrupt...
                    return(CPUExecution.INTERRUPT);
                }

                case OpCode.SET_A:
                {
                    a = new Register();

                    // Extract the lower Nibble and store it in A
                    a.SetBit(3, Helper.IsBitSet(instruction.GetByte(), 3));
                    a.SetBit(2, Helper.IsBitSet(instruction.GetByte(), 2));
                    a.SetBit(1, Helper.IsBitSet(instruction.GetByte(), 1));
                    a.SetBit(0, Helper.IsBitSet(instruction.GetByte(), 0));
                    break;
                }

                case OpCode.SET_B:
                {
                    b = new Register();

                    // Extract the lower Nibble and store it in B
                    b.SetBit(3, Helper.IsBitSet(instruction.GetByte(), 3));
                    b.SetBit(2, Helper.IsBitSet(instruction.GetByte(), 2));
                    b.SetBit(1, Helper.IsBitSet(instruction.GetByte(), 1));
                    b.SetBit(0, Helper.IsBitSet(instruction.GetByte(), 0));
                    break;
                }

                case OpCode.MOV8:
                {
                    c = new Register();

                    // Upper Nibble
                    c.SetBit(7, b.Value[3]);
                    c.SetBit(6, b.Value[2]);
                    c.SetBit(5, b.Value[1]);
                    c.SetBit(4, b.Value[0]);

                    // Lower Nibble
                    c.SetBit(3, a.Value[3]);
                    c.SetBit(2, a.Value[2]);
                    c.SetBit(1, a.Value[1]);
                    c.SetBit(0, a.Value[0]);

                    // Calculate Flags
                    SetFlags();
                    break;
                }

                case OpCode.AND:
                {
                    c = new Register();

                    // Upper Nibble
                    c.SetBit(7, a.Value[7] & b.Value[7]);
                    c.SetBit(6, a.Value[6] & b.Value[6]);
                    c.SetBit(5, a.Value[5] & b.Value[5]);
                    c.SetBit(4, a.Value[4] & b.Value[4]);

                    // Lower Nibble
                    c.SetBit(3, a.Value[3] & b.Value[3]);
                    c.SetBit(2, a.Value[2] & b.Value[2]);
                    c.SetBit(1, a.Value[1] & b.Value[1]);
                    c.SetBit(0, a.Value[0] & b.Value[0]);

                    // Calculate Flags
                    SetFlags();
                    break;
                }

                case OpCode.OR:
                {
                    c = new Register();

                    // Upper Nibble
                    c.SetBit(7, a.Value[7] | b.Value[7]);
                    c.SetBit(6, a.Value[6] | b.Value[6]);
                    c.SetBit(5, a.Value[5] | b.Value[5]);
                    c.SetBit(4, a.Value[4] | b.Value[4]);

                    // Lower Nibble
                    c.SetBit(3, a.Value[3] | b.Value[3]);
                    c.SetBit(2, a.Value[2] | b.Value[2]);
                    c.SetBit(1, a.Value[1] | b.Value[1]);
                    c.SetBit(0, a.Value[0] | b.Value[0]);

                    // Calculate Flags
                    SetFlags();
                    break;
                }

                case OpCode.XOR:
                {
                    c = new Register();

                    // Upper Nibble
                    c.SetBit(7, a.Value[7] ^ b.Value[7]);
                    c.SetBit(6, a.Value[6] ^ b.Value[6]);
                    c.SetBit(5, a.Value[5] ^ b.Value[5]);
                    c.SetBit(4, a.Value[4] ^ b.Value[4]);

                    // Lower Nibble
                    c.SetBit(3, a.Value[3] ^ b.Value[3]);
                    c.SetBit(2, a.Value[2] ^ b.Value[2]);
                    c.SetBit(1, a.Value[1] ^ b.Value[1]);
                    c.SetBit(0, a.Value[0] ^ b.Value[0]);

                    // Calculate Flags
                    SetFlags();
                    break;
                }

                case OpCode.SHL:
                {
                    c = new Register();

                    c.SetBit(7, a.Value[6]);
                    c.SetBit(6, a.Value[5]);
                    c.SetBit(5, a.Value[4]);
                    c.SetBit(4, a.Value[3]);
                    c.SetBit(3, a.Value[2]);
                    c.SetBit(2, a.Value[1]);
                    c.SetBit(1, a.Value[0]);
                    c.SetBit(0, false);

                    carrySHL = a.Value.Get(7);

                    // Calculate Flags
                    SetFlags();
                    break;
                }

                case OpCode.SHR:
                {
                    c = new Register();

                    c.SetBit(7, false);
                    c.SetBit(6, a.Value[7]);
                    c.SetBit(5, a.Value[6]);
                    c.SetBit(4, a.Value[5]);
                    c.SetBit(3, a.Value[4]);
                    c.SetBit(2, a.Value[3]);
                    c.SetBit(1, a.Value[2]);
                    c.SetBit(0, a.Value[1]);

                    carrySHR = a.Value.Get(0);

                    // Calculate Flags
                    SetFlags();
                    break;
                }

                case OpCode.ADD:
                {
                    c = new Register();
                    int  result     = a.GetInt() + b.GetInt();
                    byte byteResult = (byte)result;

                    c.SetBit(7, Helper.IsBitSet(byteResult, 7));
                    c.SetBit(6, Helper.IsBitSet(byteResult, 6));
                    c.SetBit(5, Helper.IsBitSet(byteResult, 5));
                    c.SetBit(4, Helper.IsBitSet(byteResult, 4));
                    c.SetBit(3, Helper.IsBitSet(byteResult, 3));
                    c.SetBit(2, Helper.IsBitSet(byteResult, 2));
                    c.SetBit(1, Helper.IsBitSet(byteResult, 1));
                    c.SetBit(0, Helper.IsBitSet(byteResult, 0));

                    if (result > 256)
                    {
                        carryADD = true;
                    }

                    // Calculate Flags
                    SetFlags();
                    break;
                }

                case OpCode.SUB:
                {
                    c = new Register();
                    int  result     = a.GetInt() - b.GetInt();
                    byte byteResult = (byte)result;

                    c.SetBit(7, Helper.IsBitSet(byteResult, 7));
                    c.SetBit(6, Helper.IsBitSet(byteResult, 6));
                    c.SetBit(5, Helper.IsBitSet(byteResult, 5));
                    c.SetBit(4, Helper.IsBitSet(byteResult, 4));
                    c.SetBit(3, Helper.IsBitSet(byteResult, 3));
                    c.SetBit(2, Helper.IsBitSet(byteResult, 2));
                    c.SetBit(1, Helper.IsBitSet(byteResult, 1));
                    c.SetBit(0, Helper.IsBitSet(byteResult, 0));

                    if (result < 0)
                    {
                        carrySUB = true;
                    }

                    // Calculate Flags
                    SetFlags();
                    break;
                }

                case OpCode.NOT:
                {
                    c = new Register();
                    c.SetBit(7, !a.Value[7]);
                    c.SetBit(6, !a.Value[6]);
                    c.SetBit(5, !a.Value[5]);
                    c.SetBit(4, !a.Value[4]);
                    c.SetBit(3, !a.Value[3]);
                    c.SetBit(2, !a.Value[2]);
                    c.SetBit(1, !a.Value[1]);
                    c.SetBit(0, !a.Value[0]);

                    // Calculate Flags
                    SetFlags();
                    break;
                }

                case OpCode.MOV_ALU_IN_A_D:
                {
                    a = d;
                    break;
                }

                case OpCode.MOV_ALU_IN_A_E:
                {
                    a = e;
                    break;
                }

                case OpCode.MOV_ALU_IN_A_F:
                {
                    a = f;
                    break;
                }

                case OpCode.MOV_ALU_IN_A_G:
                {
                    a = g;
                    break;
                }

                case OpCode.MOV_ALU_IN_A_H:
                {
                    a = h;
                    break;
                }

                case OpCode.MOV_ALU_IN_A_XL:
                {
                    a = xl;
                    break;
                }

                case OpCode.MOV_ALU_IN_A_XH:
                {
                    a = xh;
                    break;
                }

                case OpCode.MOV_ALU_IN_B_D:
                {
                    b = d;
                    break;
                }

                case OpCode.MOV_ALU_IN_B_E:
                {
                    b = e;
                    break;
                }

                case OpCode.MOV_ALU_IN_B_F:
                {
                    b = f;
                    break;
                }

                case OpCode.MOV_ALU_IN_B_G:
                {
                    b = g;
                    break;
                }

                case OpCode.MOV_ALU_IN_B_H:
                {
                    b = h;
                    break;
                }

                case OpCode.MOV_ALU_IN_B_XL:
                {
                    b = xl;
                    break;
                }

                case OpCode.MOV_ALU_IN_B_XH:
                {
                    b = xh;
                    break;
                }

                case OpCode.MOV_ALU_OUT_D:
                {
                    d = c;
                    break;
                }

                case OpCode.MOV_ALU_OUT_E:
                {
                    e = c;
                    break;
                }

                case OpCode.MOV_ALU_OUT_F:
                {
                    f = c;
                    break;
                }

                case OpCode.MOV_ALU_OUT_G:
                {
                    g = c;
                    break;
                }

                case OpCode.MOV_ALU_OUT_H:
                {
                    h = c;
                    break;
                }

                case OpCode.MOV_ALU_OUT_XL:
                {
                    xl = c;
                    break;
                }

                case OpCode.MOV_ALU_OUT_XH:
                {
                    xh = c;
                    break;
                }

                case OpCode.MOV_D_TO_E:
                {
                    e = d;
                    break;
                }

                case OpCode.MOV_D_TO_F:
                {
                    f = d;
                    break;
                }

                case OpCode.MOV_D_TO_G:
                {
                    g = d;
                    break;
                }

                case OpCode.MOV_D_TO_H:
                {
                    h = d;
                    break;
                }

                case OpCode.MOV_D_TO_XL:
                {
                    xl = d;
                    break;
                }

                case OpCode.MOV_D_TO_XH:
                {
                    xh = d;
                    break;
                }

                case OpCode.MOV_E_TO_D:
                {
                    d = e;
                    break;
                }

                case OpCode.MOV_E_TO_F:
                {
                    f = e;
                    break;
                }

                case OpCode.MOV_E_TO_G:
                {
                    g = e;
                    break;
                }

                case OpCode.MOV_E_TO_H:
                {
                    h = e;
                    break;
                }

                case OpCode.MOV_E_TO_XL:
                {
                    xl = e;
                    break;
                }

                case OpCode.MOV_E_TO_XH:
                {
                    xh = e;
                    break;
                }

                case OpCode.MOV_F_TO_D:
                {
                    d = f;
                    break;
                }

                case OpCode.MOV_F_TO_E:
                {
                    e = f;
                    break;
                }

                case OpCode.MOV_F_TO_G:
                {
                    g = f;
                    break;
                }

                case OpCode.MOV_F_TO_H:
                {
                    h = f;
                    break;
                }

                case OpCode.MOV_F_TO_XL:
                {
                    xl = f;
                    break;
                }

                case OpCode.MOV_G_TO_D:
                {
                    d = g;
                    break;
                }

                case OpCode.MOV_G_TO_E:
                {
                    e = g;
                    break;
                }

                case OpCode.MOV_G_TO_F:
                {
                    f = g;
                    break;
                }

                case OpCode.MOV_G_TO_H:
                {
                    h = g;
                    break;
                }

                case OpCode.MOV_G_TO_XL:
                {
                    xl = g;
                    break;
                }

                case OpCode.MOV_G_TO_XH:
                {
                    xh = g;
                    break;
                }

                case OpCode.MOV_H_TO_D:
                {
                    d = h;
                    break;
                }

                case OpCode.MOV_H_TO_E:
                {
                    e = h;
                    break;
                }

                case OpCode.MOV_H_TO_F:
                {
                    f = h;
                    break;
                }

                case OpCode.MOV_H_TO_G:
                {
                    g = h;
                    break;
                }

                case OpCode.MOV_H_TO_XL:
                {
                    xl = h;
                    break;
                }

                case OpCode.MOV_H_TO_XH:
                {
                    xh = h;
                    break;
                }

                case OpCode.MOV_XL_TO_D:
                {
                    d = xl;
                    break;
                }

                case OpCode.MOV_XL_TO_E:
                {
                    e = xl;
                    break;
                }

                case OpCode.MOV_XL_TO_F:
                {
                    f = xl;
                    break;
                }

                case OpCode.MOV_XL_TO_G:
                {
                    g = xl;
                    break;
                }

                case OpCode.MOV_XL_TO_H:
                {
                    h = xl;
                    break;
                }

                case OpCode.MOV_XL_TO_XH:
                {
                    xh = xl;
                    break;
                }

                case OpCode.MOV_XH_TO_D:
                {
                    d = xh;
                    break;
                }

                case OpCode.MOV_XH_TO_E:
                {
                    e = xh;
                    break;
                }

                case OpCode.MOV_XH_TO_F:
                {
                    f = xh;
                    break;
                }

                case OpCode.MOV_XH_TO_G:
                {
                    g = xh;
                    break;
                }

                case OpCode.MOV_XH_TO_H:
                {
                    h = xh;
                    break;
                }

                case OpCode.MOV_XH_TO_XL:
                {
                    xl = xh;
                    break;
                }

                case OpCode.MOV_M_TO_X:
                {
                    X = m;
                    break;
                }

                case OpCode.MOV_M_TO_J:
                {
                    j = m;
                    break;
                }

                case OpCode.MOV_M_TO_SP:
                {
                    sp = m;
                    break;
                }

                case OpCode.MOV_M_TO_BP:
                {
                    bp = m;
                    break;
                }

                case OpCode.MOV_M_TO_Y:
                {
                    y = m;
                    break;
                }

                case OpCode.MOV_M_TO_Z:
                {
                    z = m;
                    break;
                }

                case OpCode.MOV_M_TO_PC:
                {
                    programCounter = m;
                    break;
                }

                case OpCode.MOV_X_TO_M:
                {
                    m = X;
                    break;
                }

                case OpCode.MOV_X_TO_J:
                {
                    j = X;
                    break;
                }

                case OpCode.MOV_X_TO_SP:
                {
                    sp = X;
                    break;
                }

                case OpCode.MOV_X_TO_BP:
                {
                    bp = X;
                    break;
                }

                case OpCode.MOV_X_TO_Y:
                {
                    y = X;
                    break;
                }

                case OpCode.MOV_X_TO_Z:
                {
                    z = X;
                    break;
                }

                case OpCode.MOV_J_TO_M:
                {
                    m = j;
                    break;
                }

                case OpCode.MOV_J_TO_X:
                {
                    X = j;
                    break;
                }

                case OpCode.MOV_J_TO_SP:
                {
                    sp = j;
                    break;
                }

                case OpCode.MOV_J_TO_BP:
                {
                    bp = j;
                    break;
                }

                case OpCode.MOV_J_TO_Y:
                {
                    y = j;
                    break;
                }

                case OpCode.MOV_J_TO_Z:
                {
                    z = j;
                    break;
                }

                case OpCode.MOV_SP_TO_M:
                {
                    m = sp;
                    break;
                }

                case OpCode.MOV_SP_TO_X:
                {
                    X = sp;
                    break;
                }

                case OpCode.MOV_SP_TO_J:
                {
                    j = sp;
                    break;
                }

                case OpCode.MOV_SP_TO_BP:
                {
                    bp = sp;
                    break;
                }

                case OpCode.MOV_SP_TO_Y:
                {
                    y = sp;
                    break;
                }

                case OpCode.MOV_SP_TO_Z:
                {
                    z = sp;
                    break;
                }

                case OpCode.MOV_PC_TO_X:
                {
                    X = programCounter;
                    break;
                }

                case OpCode.MOV_BP_TO_M:
                {
                    m = bp;
                    break;
                }

                case OpCode.MOV_BP_TO_X:
                {
                    X = bp;
                    break;
                }

                case OpCode.MOV_BP_TO_J:
                {
                    j = bp;
                    break;
                }

                case OpCode.MOV_BP_TO_SP:
                {
                    sp = bp;
                    break;
                }

                case OpCode.MOV_BP_TO_Y:
                {
                    y = bp;
                    break;
                }

                case OpCode.MOV_BP_TO_Z:
                {
                    z = bp;
                    break;
                }

                case OpCode.MOV_Y_TO_M:
                {
                    m = y;
                    break;
                }

                case OpCode.MOV_Y_TO_X:
                {
                    X = y;
                    break;
                }

                case OpCode.MOV_Y_TO_J:
                {
                    j = y;
                    break;
                }

                case OpCode.MOV_Y_TO_SP:
                {
                    sp = y;
                    break;
                }

                case OpCode.MOV_Y_TO_BP:
                {
                    bp = y;
                    break;
                }

                case OpCode.MOV_Y_TO_Z:
                {
                    z = y;
                    break;
                }

                case OpCode.MOV_Z_TO_M:
                {
                    m = z;
                    break;
                }

                case OpCode.MOV_Z_TO_X:
                {
                    X = z;
                    break;
                }

                case OpCode.MOV_Z_TO_J:
                {
                    j = z;
                    break;
                }

                case OpCode.MOV_Z_TO_SP:
                {
                    sp = z;
                    break;
                }

                case OpCode.MOV_Z_TO_BP:
                {
                    bp = z;
                    break;
                }

                case OpCode.MOV_Z_TO_Y:
                {
                    y = z;
                    break;
                }

                case OpCode.MOV_ALU_C_TO_A:
                {
                    a = c;
                    break;
                }

                case OpCode.MOV_ALU_C_TO_B:
                {
                    b = c;
                    break;
                }

                case OpCode.LOAD_D:
                {
                    d.SetBits(ram.ReadValue(M.GetInt()));
                    break;
                }

                case OpCode.LOAD_E:
                {
                    e.SetBits(ram.ReadValue(M.GetInt()));
                    break;
                }

                case OpCode.LOAD_F:
                {
                    f.SetBits(ram.ReadValue(M.GetInt()));
                    break;
                }

                case OpCode.LOAD_G:
                {
                    g.SetBits(ram.ReadValue(M.GetInt()));
                    break;
                }

                case OpCode.LOAD_H:
                {
                    h.SetBits(ram.ReadValue(M.GetInt()));
                    break;
                }

                case OpCode.LOAD_XL:
                {
                    xl.SetBits(ram.ReadValue(M.GetInt()));
                    break;
                }

                case OpCode.LOAD_XH:
                {
                    xh.SetBits(ram.ReadValue(M.GetInt()));
                    break;
                }

                case OpCode.STORE_D:
                {
                    ram.WriteValue(M.GetInt(), d.GetByte());
                    break;
                }

                case OpCode.STORE_E:
                {
                    ram.WriteValue(M.GetInt(), e.GetByte());
                    break;
                }

                case OpCode.STORE_F:
                {
                    ram.WriteValue(M.GetInt(), f.GetByte());
                    break;
                }

                case OpCode.STORE_G:
                {
                    ram.WriteValue(M.GetInt(), g.GetByte());
                    break;
                }

                case OpCode.STORE_H:
                {
                    ram.WriteValue(M.GetInt(), h.GetByte());
                    break;
                }

                case OpCode.STORE_XL:
                {
                    ram.WriteValue(M.GetInt(), xl.GetByte());
                    break;
                }

                case OpCode.STORE_XH:
                {
                    ram.WriteValue(M.GetInt(), xh.GetByte());
                    break;
                }

                case OpCode.SAVE_FLAGS:
                {
                    flagsSaved = flags;
                    break;
                }

                case OpCode.RESTORE_FLAGS:
                {
                    flags = flagsSaved;
                    break;
                }

                case OpCode.JMP:
                {
                    programCounter          = j;
                    incrementProgramCounter = false;
                    break;
                }

                case OpCode.JZ:
                {
                    // The Jump is only performed if the Zero Flag is set to 1
                    if (flags.Value.Get(1))
                    {
                        programCounter          = j;
                        incrementProgramCounter = false;
                    }
                    else
                    {
                        incrementProgramCounter = true;
                    }

                    break;
                }

                case OpCode.JNZ:
                {
                    // The Jump is only performed if the Zero Flag is set to 0
                    if (!flags.Value.Get(1))
                    {
                        programCounter          = j;
                        incrementProgramCounter = false;
                    }
                    else
                    {
                        incrementProgramCounter = true;
                    }

                    break;
                }

                case OpCode.JNS:
                {
                    // The Jump is only performed if the Sign Flag is set to 0
                    if (!flags.Value.Get(0))
                    {
                        programCounter          = j;
                        incrementProgramCounter = false;
                    }
                    else
                    {
                        incrementProgramCounter = true;
                    }

                    break;
                }

                case OpCode.ADDER_16BIT:
                {
                    int result = X.GetInt() + J.GetInt();

                    Register16 temp = new Register16();
                    temp.SetBits(result);
                    X = temp;

                    break;
                }

                case OpCode.OUT_C:
                {
                    OutputPortC = xl.GetString();
                    break;
                }

                case OpCode.OUT_D:
                {
                    OutputPortD = xl.GetString();
                    break;
                }

                case OpCode.IN_A:
                {
                    programCounter.Increment();
                    return(CPUExecution.IN_A);
                }

                case OpCode.IN_B:
                {
                    programCounter.Increment();
                    return(CPUExecution.IN_B);
                }
                }
            }
            else
            {
                // We hit a breakpoint!
                return(CPUExecution.BREAKPOINT_HIT);
            }

            // Increment the Program Counter, if necessary
            if (incrementProgramCounter)
            {
                programCounter.Increment();
            }

            // There are more CPU instructions available for execution...
            return(CPUExecution.MORE_INSTRUCTIONS_AVAILABLE);
        }