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)); } }
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); }
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); }
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(); } }
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"); } }
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); }
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); } }
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(); } }
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); }
public void ConvertStringToMovementWithNullValueShouldThrowException() { Assert.ThrowsException <ArgumentNullException>(() => { var result = InstructionHelper.ConvertStringToMovement(null); }); }
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(); } }
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)); }
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); }
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(); } }
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)); }
public void ConvertHeadingToStringWithWValueShouldReturnInteger() { var value = Heading.West; var result = InstructionHelper.ConvertHeadingToString(value); Assert.AreEqual("W", result); }
public void ConvertStringToMovementWithLowerMValueShouldReturnMovement() { var value = "m"; var result = InstructionHelper.ConvertStringToMovement(value); Assert.AreEqual(Movement.Move, result); }
public void ConvertStringToHeadingWithLowerWValueShouldReturnInteger() { var value = "w"; var result = InstructionHelper.ConvertStringToHeading(value); Assert.AreEqual(Heading.West, result); }
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)); }
public void ConvertToIntWithZeroValueShouldReturnInteger() { var value = "0"; var result = InstructionHelper.ConvertToInt(value); Assert.AreEqual(int.Parse(value), result); }
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); }
public void ConvertToIntWithInvalidValueShouldThrowException() { var value = "foo"; Assert.ThrowsException <FormatException>(() => { var result = InstructionHelper.ConvertToInt(value); }); }
public void ConvertStringToHeadingWithInvalidValueShouldThrowException() { var value = "foo"; Assert.ThrowsException <ArgumentException>(() => { var result = InstructionHelper.ConvertStringToHeading(value); }); }
public void SplitLineWithEmptyValueReturnsEmptyResult() { var line = string.Empty; var count = 0; var result = InstructionHelper.SplitLine(line, count); Assert.AreEqual(count, result.Length); }
public void ConvertStringToMovementWithEmptyValueShouldThrowException() { var value = string.Empty; Assert.ThrowsException <ArgumentException>(() => { var result = InstructionHelper.ConvertStringToMovement(value); }); }
public void ConvertStringToMovementWithInvalidSingleCharacterValueShouldThrowException() { var value = "Z"; Assert.ThrowsException <ArgumentException>(() => { var result = InstructionHelper.ConvertStringToMovement(value); }); }
public void SplitLineWithTwoValueThrowsExceptionWhenExpectingThree() { var line = "1 2"; var count = 3; Assert.ThrowsException <ArgumentException>(() => { var result = InstructionHelper.SplitLine(line, count); }); }