Ejemplo n.º 1
0
        public void Step()
        {
            _recoveryFlag = false;
            _haltFlag = false;

            if (InstructionPointer < 0 || InstructionPointer >= _program.Count)
            {
                _haltFlag = true;
                return;
            }

            var instruction = _program[(int)InstructionPointer];

            var disasseblyA = "";
            long valueA = 0;
            if (instruction.ValueA.HasValue)
            {
                valueA = instruction.ValueA.Value;
                disasseblyA = valueA.ToString();
            }

            if (instruction.RegisterA.HasValue)
            {
                valueA = GetRegister(instruction.RegisterA.Value);
                disasseblyA = instruction.RegisterA.Value.ToString();
            }

            var disasseblyB = "";
            long valueB = 0;
            if (instruction.ValueB.HasValue)
            {
                valueB = instruction.ValueB.Value;
                disasseblyB = valueB.ToString();
            }

            if (instruction.RegisterB.HasValue)
            {
                valueB = GetRegister(instruction.RegisterB.Value);
                disasseblyB = instruction.RegisterB.Value.ToString();
            }

            if (Disassembly)
            {
                Console.WriteLine(InstructionPointer + ": " + _opcodesLookup.Single(i => i.Value == instruction.Opcode).Key + " " + disasseblyA + " " + disasseblyB);
            }


            switch (instruction.Opcode)
            {
                case Opcode.Snd:
                    SendCount++;
                    _recoveryFrequency = valueA;
                    Send.Add(_recoveryFrequency);
                    //Console.WriteLine($"sound: {_recoveryFrequency}");
                    break;

                case Opcode.Set:
                    SetRegister(instruction.RegisterA.Value, valueB);
                    break;

                case Opcode.Add:
                    var add = valueA;
                    add += valueB;
                    SetRegister(instruction.RegisterA.Value, add);
                    break;

                case Opcode.Sub:
                    var sub = valueA;
                    sub -= valueB;
                    SetRegister(instruction.RegisterA.Value, sub);
                    break;

                case Opcode.Mul:
                    MulCount++;
                    var mul = valueA;
                    mul *= valueB;
                    SetRegister(instruction.RegisterA.Value, mul);
                    break;

                case Opcode.Mod:
                    var mod = valueA;
                    mod %= valueB;
                    SetRegister(instruction.RegisterA.Value, mod);
                    break;

                case Opcode.Rcv:
                    if (valueA != 0)
                    {
                        if (_recoveryFrequency > 0)
                        {
                            _recoveryFlag = true;//part 1
                        }
                    }

                    if (Received.Any())
                    {
                        _recoveryFlag = false;
                        var received = Received.First();
                        Received.RemoveAt(0);
                        SetRegister(instruction.RegisterA.Value, received);
                    }
                    else//If 
                    {
                        //Return, skipping increment of instruction ptr
                        _recoveryFlag = true;
                        return;
                    }
                    break;

                case Opcode.Jgz:
                    if (valueA > 0)
                    {
                        InstructionPointer += valueB;
                    }
                    else
                    {
                        InstructionPointer++;
                    }
                    break;

                case Opcode.Jnz:
                    if (valueA != 0)
                    {
                        InstructionPointer += valueB;
                    }
                    else
                    {
                        InstructionPointer++;
                    }
                    break;

                default:
                    throw new Exception();
            }

            if (instruction.Opcode != Opcode.Jgz && instruction.Opcode != Opcode.Jnz)
            {
                InstructionPointer++;
            }
            StepCount++;
        }