Beispiel #1
0
        void Halt(HaltCode code)
        {
            // TODO: add halt reasong as parameter and support in translator
            NextState.State    = CPUState.Halt;
            NextState.HaltCode = code;

            // calls to Debugger and Trace are not translated into HDL.
            Trace.WriteLine($"CPU halted: {code}");
            Debugger.Break();
        }
Beispiel #2
0
        /// <summary>
        /// Execute a program
        /// </summary>
        /// <returns>Boolean based on how program stopped, false if it can be continued (opcode 99) or true if its waiting on input</returns>
        public HaltCode ExecuteProgram(int startOpcodeAddress = 0)
        {
            // stop immediately if start address is out of memory
            if (startOpcodeAddress < 0 || startOpcodeAddress >= memory.Length)
            {
                LastHaltCode = HaltCode.InvalidPointer;
                return(HaltCode.InvalidPointer);
            }

            // pointer to address of current opcode
            int opcodePointer = startOpcodeAddress;

            // possible parameters
            long a, b;

            while (true)
            {
                // get op code
                long opCode = memory[opcodePointer];

                long[] param;
                switch (opCode % 100)
                {
                // +
                case 1:
                    param = GetParameters(opcodePointer, 2);
                    a     = param[0];
                    b     = param[1];

                    if ((memory[opcodePointer] / 100_0_0) % 10 == 2)
                    {
                        SetMemory(memory[opcodePointer + 3] + relativeBase, a + b);
                    }
                    else if ((memory[opcodePointer] / 100_0_0) % 10 == 0)
                    {
                        SetMemory(memory[opcodePointer + 3], a + b);
                    }
        /// <summary>
        /// Execute loaded program
        /// </summary>
        /// <returns>Reason for halting VM</returns>
        public HaltCode ExecuteProgram(long startAddress = 0)
        {
            // stop immediately if start address is negative
            if (startAddress < 0)
            {
                LastHaltReason = HaltCode.InvalidOpCodePointer;
                return(HaltCode.InvalidOpCodePointer);
            }

            // pointer to address of current opcode
            long opcodePointer = startAddress;

            // parameters
            long[] longParams;

            // execute program
            while (true)
            {
                long opCode = GetMemory(opcodePointer);

                // instruction
                switch (opCode % 100)
                {
                // addition
                case 1:
                    longParams = GetParamAddresses(opcodePointer, 3);

                    SetMemory(longParams[2], GetMemory(longParams[0]) + GetMemory(longParams[1]));

                    opcodePointer += 4;
                    break;

                // multiplication
                case 2:
                    longParams = GetParamAddresses(opcodePointer, 3);

                    SetMemory(longParams[2], GetMemory(longParams[0]) * GetMemory(longParams[1]));

                    opcodePointer += 4;
                    break;

                // get input
                case 3:
                    longParams = GetParamAddresses(opcodePointer, 1);

                    long?input = GetNextInput();

                    // halt VM till input is given
                    if (input == null)
                    {
                        pausedOpCodePointer = opcodePointer;
                        LastHaltReason      = HaltCode.WaitingForInput;
                        return(HaltCode.WaitingForInput);
                    }
                    else
                    {
                        SetMemory(longParams[0], (long)input);
                    }

                    opcodePointer += 2;
                    break;

                // output
                case 4:
                    longParams = GetParamAddresses(opcodePointer, 1);

                    outputs.Add(GetMemory(longParams[0]));

                    opcodePointer += 2;
                    break;

                // jump if not zero
                case 5:
                    longParams = GetParamAddresses(opcodePointer, 2);

                    if (GetMemory(longParams[0]) != 0L)
                    {
                        opcodePointer = GetMemory(longParams[1]);
                    }
                    else
                    {
                        opcodePointer += 3;
                    }
                    break;

                // jump if zero
                case 6:
                    longParams = GetParamAddresses(opcodePointer, 2);

                    if (GetMemory(longParams[0]) == 0L)
                    {
                        opcodePointer = GetMemory(longParams[1]);
                    }
                    else
                    {
                        opcodePointer += 3;
                    }
                    break;

                // less than
                case 7:
                    longParams = GetParamAddresses(opcodePointer, 3);

                    SetMemory(longParams[2], GetMemory(longParams[0]) < GetMemory(longParams[1]) ? 1 : 0);

                    opcodePointer += 4;
                    break;

                // equals
                case 8:
                    longParams = GetParamAddresses(opcodePointer, 3);

                    SetMemory(longParams[2], GetMemory(longParams[0]) == GetMemory(longParams[1]) ? 1 : 0);

                    opcodePointer += 4;
                    break;

                // change base offset
                case 9:
                    longParams = GetParamAddresses(opcodePointer, 1);

                    baseOffset += GetMemory(longParams[0]);

                    opcodePointer += 2;
                    break;

                // end program
                case 99:
                    LastHaltReason = HaltCode.Finished;
                    return(HaltCode.Finished);

                // unknown opcode
                default:
                    // write error to console
                    Console.BackgroundColor = ConsoleColor.Black;
                    Console.ForegroundColor = ConsoleColor.Red;

                    Console.WriteLine($"Fatal VM error: unknown opcode {opCode % 100} ({opCode}) at address {opcodePointer}");

                    Console.ForegroundColor = ConsoleColor.White;

                    LastHaltReason = HaltCode.UnknownOpCode;
                    return(HaltCode.UnknownOpCode);
                }
            }
        }
 public void Visit(HaltCode code)
 {
 }