Beispiel #1
0
        public void Dispatch(Cpu8086 cpu, OpCodeManager.Instruction instruction)
        {
            var prefix = instruction.SegmentPrefix;

            if (prefix == Register.Invalid)
            {
                prefix = Register.DS;
            }
            var sourceAddress = InstructionHelper.SegmentToAddress(cpu.GetRegister(prefix), cpu.GetRegister(Register.SI));

            byte size;

            if (instruction.Flag.Has(OpCodeManager.OpCodeFlag.Size8))
            {
                cpu.SetRegisterU8(Register.AL, cpu.ReadU8(sourceAddress));
                size = 1;
            }
            else
            {
                cpu.SetRegister(Register.AX, cpu.ReadU16(sourceAddress));
                size = 2;
            }

            if (!cpu.GetFlags().Has(FlagsRegister.Direction))
            {
                cpu.SetRegister(Register.SI, (ushort)(cpu.GetRegister(Register.SI) + size));
            }
            else
            {
                cpu.SetRegister(Register.SI, (ushort)(cpu.GetRegister(Register.SI) - size));
            }
        }
Beispiel #2
0
        public void Define(MethodBody methodBody)
        {
            var boolean   = methodBody.AddVariable(typeSystem.Boolean);
            var processor = methodBody.GetILProcessor();
            var jumpLabel = Instruction.Create(OpCodes.Nop);

            //if(collection.Count < 0)
            processor.Emit(OpCodes.Ldarg_0);
            processor.Emit(OpCodes.Ldfld, list);

            //get_count()
            processor.Emit(OpCodes.Callvirt, getCount);
            processor.Emit(OpCodes.Ldc_I4_0);
            processor.Emit(OpCodes.Cgt);
            processor.Append(InstructionHelper.StLoc(boolean));
            processor.Append(InstructionHelper.LdLoc(boolean));
            processor.Emit(OpCodes.Brfalse_S, jumpLabel);

            //collection.Clear();
            processor.Emit(OpCodes.Ldarg_0);
            processor.Emit(OpCodes.Ldfld, list);

            //clear()
            processor.Emit(OpCodes.Callvirt, clear);

            processor.Emit(OpCodes.Nop);
            processor.Append(jumpLabel);
        }
Beispiel #3
0
        public void Dispatch(Cpu8086 cpu, OpCodeManager.Instruction instruction)
        {
            var address = InstructionHelper.GetInstructionValue(cpu, instruction.Flag, instruction.SegmentPrefix, instruction.Argument1, instruction.Argument1Value, instruction.Argument1Displacement);

            cpu.Push(cpu.GetRegister(Register.IP));
            cpu.SetRegister(Register.IP, address);
        }
Beispiel #4
0
        public void Dispatch(Cpu8086 cpu, OpCodeManager.Instruction instruction)
        {
            switch (instruction.Argument1)
            {
            case (int)Register.SP:
            // 8086 has a bug where it pushes SP after it has been modified
            // cpu.registers[(int)Register.SP] -= 2;
            // cpu.WriteU16(SegmentToAddress(cpu.GetRegister(Register.SS), cpu.GetRegister(Register.SP)), cpu.GetRegister(Register.SP));
            // break;
            case (int)Register.AX:
            case (int)Register.CX:
            case (int)Register.DX:
            case (int)Register.BX:
            case (int)Register.BP:
            case (int)Register.SI:
            case (int)Register.DI:
            case (int)Register.IP:
            case (int)Register.CS:
            case (int)Register.DS:
            case (int)Register.ES:
            case (int)Register.SS:
            case unchecked ((int)Register.FLAGS):
                cpu.Push(cpu.GetRegister((Register)instruction.Argument1));
                break;

            case OpCodeManager.ARG_DEREFERENCE:
            case OpCodeManager.ARG_MEMORY:
                var address = InstructionHelper.GetInstructionRealAddress(cpu, instruction.SegmentPrefix, instruction.Argument1, instruction.Argument1Value, instruction.Argument1Displacement);
                cpu.Push(cpu.ReadU16(address));
                break;

            default:
                throw new ArgumentOutOfRangeException();
            }
        }
Beispiel #5
0
        private const byte Rsh = 4; // reg >>= rhs

        public static void Emit(byte[] instruction, CompilationContext context)
        {
            // 7T0RC000 VVVVVVVV
            // T: Width of arithmetic operation(1, 2, 4, or 8 bytes).
            // R: Register to apply arithmetic to.
            // C: Arithmetic operation to apply, see below.
            // V: Value to use for arithmetic operation.

            byte          operationWidth     = instruction[OperationWidthIndex];
            Register      register           = context.GetRegister(instruction[DestinationRegisterIndex]);
            byte          operation          = instruction[OperationTypeIndex];
            ulong         immediate          = InstructionHelper.GetImmediate(instruction, ValueImmediateIndex, ValueImmediateSize);
            Value <ulong> rightHandSideValue = new Value <ulong>(immediate);

            void Emit(Type operationType)
            {
                InstructionHelper.Emit(operationType, operationWidth, context, register, register, rightHandSideValue);
            }

            switch (operation)
            {
            case Add: Emit(typeof(OpAdd <>)); break;

            case Sub: Emit(typeof(OpSub <>)); break;

            case Mul: Emit(typeof(OpMul <>)); break;

            case Lsh: Emit(typeof(OpLsh <>)); break;

            case Rsh: Emit(typeof(OpRsh <>)); break;

            default:
                throw new TamperCompilationException($"Invalid arithmetic operation {operation} in Atmosphere cheat");
            }
        }
Beispiel #6
0
 public void SplitLineWithNullValueThrowsException()
 {
     Assert.ThrowsException <NullReferenceException>(() =>
     {
         var result = InstructionHelper.SplitLine(null, 0);
     });
 }
 public void End()
 {
     cacheCollection.AddValue(methodBody, MainLoop.LocalDefinition);
     MainLoop.End(methodBody);
     cacheCollection.ReturnValue(methodBody);
     InstructionHelper.Return(methodBody);
 }
Beispiel #8
0
        public void Dispatch(Cpu8086 cpu, OpCodeManager.Instruction instruction)
        {
            ushort value1;
            ushort value2;
            byte   size;

            if (instruction.Flag.Has(OpCodeManager.OpCodeFlag.Size8))
            {
                value1 = cpu.GetRegisterU8(Register.AL);
                value2 = cpu.ReadU8(InstructionHelper.SegmentToAddress(cpu.GetRegister(Register.ES), cpu.GetRegister(Register.DI)));
                size   = 1;
            }
            else
            {
                value1 = cpu.GetRegister(Register.AX);
                value2 = cpu.ReadU16(InstructionHelper.SegmentToAddress(cpu.GetRegister(Register.ES), cpu.GetRegister(Register.DI)));
                size   = 2;
            }
            var result = value1 - value2;

            InstructionHelper.CalculateSubFlags(cpu, instruction.Flag, value1, value2, result);

            if (!cpu.GetFlags().Has(FlagsRegister.Direction))
            {
                cpu.IncRegister(Register.DI, size);
            }
            else
            {
                cpu.DecRegister(Register.DI, size);
            }
        }
Beispiel #9
0
        public void Dispatch(Cpu8086 cpu, OpCodeManager.Instruction instruction)
        {
            var address = InstructionHelper.GetInstructionAddress(cpu, instruction.Argument2, instruction.Argument2Value, instruction.Argument2Displacement);

            switch ((Register)instruction.Argument1)
            {
            case Register.AX:
            case Register.CX:
            case Register.DX:
            case Register.BX:
            case Register.SP:
            case Register.BP:
            case Register.SI:
            case Register.DI:
            case Register.IP:
            case Register.CS:
            case Register.DS:
            case Register.ES:
            case Register.SS:
                cpu.SetRegister((Register)instruction.Argument1, address);
                break;

            default:
                throw new NotImplementedException();
            }
        }
Beispiel #10
0
        private ushort AssembleInstruction(string line)
        {
            var keywords    = line.Split(' ');
            var instruction = GetInstruction(keywords[0]);

            switch (InstructionHelper.GetInstructionClass(instruction))
            {
            case ClassCodification.B1:
                instruction = AssembleInstructionB1(instruction, keywords);
                break;

            case ClassCodification.B2:
                instruction = AssembleInstructionB2(instruction, keywords[1]);
                break;

            case ClassCodification.B3:
                instruction = AssembleInstructionB3(instruction, keywords[1]);
                break;

            case ClassCodification.B4:
                return(instruction);

                break;

            default:
                throw new ArgumentOutOfRangeException();
            }

            return(instruction);
        }
Beispiel #11
0
 public void ConvertStringToMovementWithNullValueShouldThrowException()
 {
     Assert.ThrowsException <ArgumentNullException>(() =>
     {
         var result = InstructionHelper.ConvertStringToMovement(null);
     });
 }
Beispiel #12
0
        public void Dispatch(Cpu8086 cpu, OpCodeManager.Instruction instruction)
        {
            switch (instruction.Argument1)
            {
            case (int)Register.AX:
            case (int)Register.CX:
            case (int)Register.DX:
            case (int)Register.BX:
            case (int)Register.SP:
            case (int)Register.BP:
            case (int)Register.SI:
            case (int)Register.DI:
            case (int)Register.IP:
            case (int)Register.CS:
            case (int)Register.DS:
            case (int)Register.ES:
            case (int)Register.SS:
                //case unchecked((int)Register.FLAGS):
                cpu.SetRegister((Register)instruction.Argument1, cpu.Pop());
                break;

            case unchecked ((int)Register.FLAGS):
                cpu.SetRegister((Register)instruction.Argument1, cpu.Pop());
                break;

            case OpCodeManager.ARG_DEREFERENCE:
            case OpCodeManager.ARG_MEMORY:
                var address = InstructionHelper.GetInstructionRealAddress(cpu, instruction.SegmentPrefix, instruction.Argument1, instruction.Argument1Value, instruction.Argument1Displacement);
                cpu.WriteU16(address, cpu.Pop());
                break;

            default:
                throw new ArgumentOutOfRangeException();
            }
        }
Beispiel #13
0
        private ushort ManageRegister(ushort instruction, string register, int bitsToShift)
        {
            switch (InstructionHelper.GetAddressingMode(instruction, bitsToShift))
            {
            case AccessMode.IMMEDIATE:
                AddValueToMemory(register);
                break;

            case AccessMode.DIRECT:
                instruction = AddRegisterToInstruction(instruction, register, bitsToShift);
                break;

            case AccessMode.INDIRECT:
                instruction = AddIndirectAccessToInstruction(instruction, register, bitsToShift);
                break;

            case AccessMode.INDEXED:
                instruction = AddIndexedAccessToInstruction(instruction, register, bitsToShift);
                break;

            default:
                throw new AccessModeException($"{register} has no known access mode");
            }

            return(instruction);
        }
        public static void Emit(byte[] instruction, CompilationContext context)
        {
            // C3000XXx
            // XX: Static register index, 0x00 to 0x7F for reading or 0x80 to 0xFF for writing.
            // x: Register index.

            ulong    staticRegisterIndex = InstructionHelper.GetImmediate(instruction, StaticRegisterIndex, StaticRegisterSize);
            Register register            = context.GetRegister(instruction[RegisterIndex]);

            IOperand sourceRegister;
            IOperand destinationRegister;

            if (staticRegisterIndex < FirstWriteRegister)
            {
                // Read from static register.
                sourceRegister      = context.GetStaticRegister((byte)staticRegisterIndex);
                destinationRegister = register;
            }
            else
            {
                // Write to static register.
                sourceRegister      = register;
                destinationRegister = context.GetStaticRegister((byte)(staticRegisterIndex - FirstWriteRegister));
            }

            context.CurrentOperations.Add(new OpMov <ulong>(destinationRegister, sourceRegister));
        }
Beispiel #15
0
        public void End(MethodBody methodBody)
        {
            var withInVariable = methodBody.AddVariableDefinition(typeSystem.Boolean);
            var processor      = methodBody.GetILProcessor();

            //loop end
            processor.Append(loopEnd);

            //i++
            processor.Append(IncrementIndex);
            processor.Emit(OpCodes.Ldc_I4_1);
            processor.Emit(OpCodes.Add);
            processor.Append(InstructionHelper.StLoc(indexDefinition));

            //i < arr.Length
            processor.Append(loopCheck);

            //arr.Length
            processor.Append(InstructionHelper.LdArg(1));
            processor.Emit(OpCodes.Ldlen);
            processor.Emit(OpCodes.Conv_I4);

            processor.Emit(OpCodes.Clt);
            processor.Append(InstructionHelper.StLoc(withInVariable));

            //check within range
            processor.Append(InstructionHelper.LdLoc(withInVariable));
            processor.Emit(OpCodes.Brtrue_S, loopStart);
        }
Beispiel #16
0
        public void Dispatch(Cpu8086 cpu, OpCodeManager.Instruction instruction)
        {
            var address = InstructionHelper.GetInstructionRealAddress(cpu, instruction.SegmentPrefix, instruction.Argument2, instruction.Argument2Value, instruction.Argument2Displacement);
            var memory  = cpu.ReadU16(address);
            var segment = cpu.ReadU16(address + 2);

            cpu.SetRegister(_register, segment);
            switch ((Register)instruction.Argument1)
            {
            case Register.AX:
            case Register.CX:
            case Register.DX:
            case Register.BX:
            case Register.SP:
            case Register.BP:
            case Register.SI:
            case Register.DI:
            case Register.IP:
            case Register.CS:
            case Register.DS:
            case Register.ES:
            case Register.SS:
                cpu.SetRegister((Register)instruction.Argument1, memory);
                break;

            default:
                throw new NotImplementedException();
            }
        }
Beispiel #17
0
        public void Dispatch(Cpu8086 cpu, OpCodeManager.Instruction instruction)
        {
            var value1 = cpu.GetRegister(Register.AX);
            var value2 = InstructionHelper.GetInstructionValue(cpu, instruction.Flag, instruction.SegmentPrefix, instruction.Argument1, instruction.Argument1Value, instruction.Argument1Displacement);

            if (instruction.Flag.Has(OpCodeManager.OpCodeFlag.Size8))
            {
                value1 &= 0xFF;
                value2 &= 0xFF;
            }

            uint result;

            switch (instruction.Type)
            {
            case OpCodeManager.InstructionType.Multiply:
                result = (uint)value1 * value2;
                break;

            case OpCodeManager.InstructionType.SignedMultiply:
                result = (uint)(value1 * value2);
                break;

            default:
                throw new ArgumentOutOfRangeException();
            }

            InstructionHelper.CalculateAddFlags(cpu, instruction.Flag, value1, value2, (int)result);

            cpu.SetRegister(Register.AX, (ushort)result);
            if (!instruction.Flag.Has(OpCodeManager.OpCodeFlag.Size8))
            {
                cpu.SetRegister(Register.DX, (ushort)(result >> 16));
            }
        }
        public override string Solve()
        {
            var lines   = InputReader.ReadLines();
            var steps   = new StepFactory(_settings.StepSettings).Create(lines);
            var orderer = new InstructionHelper();

            return(orderer.Order(steps));
        }
Beispiel #19
0
        public void ConvertHeadingToStringWithWValueShouldReturnInteger()
        {
            var value = Heading.West;

            var result = InstructionHelper.ConvertHeadingToString(value);

            Assert.AreEqual("W", result);
        }
Beispiel #20
0
        public void ConvertStringToMovementWithLowerMValueShouldReturnMovement()
        {
            var value = "m";

            var result = InstructionHelper.ConvertStringToMovement(value);

            Assert.AreEqual(Movement.Move, result);
        }
Beispiel #21
0
        public void ConvertStringToHeadingWithLowerWValueShouldReturnInteger()
        {
            var value = "w";

            var result = InstructionHelper.ConvertStringToHeading(value);

            Assert.AreEqual(Heading.West, result);
        }
Beispiel #22
0
        public void Dispatch(Cpu8086 cpu, OpCodeManager.Instruction instruction)
        {
            var al = cpu.GetRegister(Register.AL);

            cpu.SetRegister(Register.AH, (byte)(al / 10));
            cpu.SetRegister(Register.AL, (byte)(al % 10));
            InstructionHelper.CalculateBitwiseFlags(cpu, instruction.Flag, al, 0, cpu.GetRegister(Register.AX));
        }
Beispiel #23
0
        public void ConvertToIntWithZeroValueShouldReturnInteger()
        {
            var value = "0";

            var result = InstructionHelper.ConvertToInt(value);

            Assert.AreEqual(int.Parse(value), result);
        }
Beispiel #24
0
        public override bool Optimize(OptimizationContext context)
        {
            var changed = false;

            for (var i = context.Count - 1; i >= 0; i--)
            {
                var instructionCount = context.Count;
                var instruction      = context[i];
                switch (instruction.Type)
                {
                // TODO: Can we optimize a Call-instruction here?
                case InstructionType.Char:
                case InstructionType.BoundsCheck:
                case InstructionType.Jump:
                {
                    var backtracer = new BacktracerView(context.Backtracer, i, true);
                    if (!instruction.IsCharOrBoundsCheck)
                    {
                        backtracer = new BacktracerView(context.Backtracer, i - 1, false);
                    }

                    var result = InstructionHelper.FindJumpTargetEx(context, backtracer, context.GetLabelPosition(instruction.Label), FullPathSearch, false);
                    if (!context[result.Position - 1].Matches(InstructionType.MarkLabel, instruction.Label))
                    {
                        if (context[result.Position - 1].Matches(InstructionType.MarkLabel, out var newTarget))
                        {
                            context.NonDestructiveUpdate(i, instruction.WithLabel(newTarget));
                        }
                        else
                        {
                            var newLabel = context.LabelAllocator++;
                            context.NonDestructiveUpdate(i, instruction.WithLabel(newLabel));
                            context.Insert(result.Position, Instruction.MarkLabel(newLabel), true);
                        }

                        changed = true;
                    }
                }
                break;
                }
            }

            for (var i = context.Count - 1; i >= 0; i--)
            {
                var instructionCount = context.Count;
                var instruction      = context[i];
                if (instruction.Matches(InstructionType.Jump, out var targetLabel))
                {
                    var jumpingTo = context[context.GetLabelPosition(targetLabel) + 1];
                    if (jumpingTo.Matches(InstructionType.Return))
                    {
                        context[i] = jumpingTo;
                    }
                }
            }

            return(changed);
        }
Beispiel #25
0
        public void ConvertToIntWithInvalidValueShouldThrowException()
        {
            var value = "foo";

            Assert.ThrowsException <FormatException>(() =>
            {
                var result = InstructionHelper.ConvertToInt(value);
            });
        }
Beispiel #26
0
        public void ConvertStringToHeadingWithInvalidValueShouldThrowException()
        {
            var value = "foo";

            Assert.ThrowsException <ArgumentException>(() =>
            {
                var result = InstructionHelper.ConvertStringToHeading(value);
            });
        }
Beispiel #27
0
        public void SplitLineWithEmptyValueReturnsEmptyResult()
        {
            var line  = string.Empty;
            var count = 0;

            var result = InstructionHelper.SplitLine(line, count);

            Assert.AreEqual(count, result.Length);
        }
Beispiel #28
0
        public void ConvertStringToMovementWithEmptyValueShouldThrowException()
        {
            var value = string.Empty;

            Assert.ThrowsException <ArgumentException>(() =>
            {
                var result = InstructionHelper.ConvertStringToMovement(value);
            });
        }
Beispiel #29
0
        public void ConvertStringToMovementWithInvalidSingleCharacterValueShouldThrowException()
        {
            var value = "Z";

            Assert.ThrowsException <ArgumentException>(() =>
            {
                var result = InstructionHelper.ConvertStringToMovement(value);
            });
        }
Beispiel #30
0
        public void SplitLineWithTwoValueThrowsExceptionWhenExpectingThree()
        {
            var line  = "1 2";
            var count = 3;

            Assert.ThrowsException <ArgumentException>(() =>
            {
                var result = InstructionHelper.SplitLine(line, count);
            });
        }