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(); }
/// <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) { }